- {{ _("With this certification, you can now showcase your updated skills and share your achievement with your colleagues and on LinkedIn. To access your certificate, please click on the link provided below.") }}
+ {{ _("With this certification, you can now showcase your updated skills and share your achievement with your colleagues and on LinkedIn. To access your certificate, please click on the link provided below. Make sure you are logged in to the portal.") }}
{{ _("Once again, congratulations on this significant accomplishment.")}}
diff --git a/lms/templates/emails/job_application.html b/lms/templates/emails/job_application.html
new file mode 100644
index 00000000..23b17530
--- /dev/null
+++ b/lms/templates/emails/job_application.html
@@ -0,0 +1,14 @@
+
+ {{ _("{0} has applied for the job position {1}").format(full_name, job_title) }}
+
+
- {{ frappe.utils.pretty_date(review.creation) }}
+ {{ review.creation }}
diff --git a/lms/templates/reviews_cta.html b/lms/templates/reviews_cta.html
index 85def038..f10250ae 100644
--- a/lms/templates/reviews_cta.html
+++ b/lms/templates/reviews_cta.html
@@ -1,4 +1,4 @@
-{% if is_eligible_to_review(course.name, membership) %}
+{% if membership and is_eligible_to_review(course.name) %}
{{ _("Write a review") }}
diff --git a/lms/www/assignment_submission/assignment_submission.html b/lms/www/assignment_submission/assignment_submission.html
deleted file mode 100644
index 253a8004..00000000
--- a/lms/www/assignment_submission/assignment_submission.html
+++ /dev/null
@@ -1,181 +0,0 @@
-{% extends "lms/templates/lms_base.html" %}
-{% block title %}
- {{ assignment.title }}
-{% endblock %}
-
-{% block page_content %}
-
- {{ Header() }}
-
- {{ SubmissionForm(assignment) }}
-
-
-{% endblock %}
-
-{% macro Header() %}
-
-{% endmacro %}
-
-{% macro SubmissionForm(assignment) %}
-
- {% if assignment.grade_assignment and submission.name %}
-
- {{ _("You've successfully submitted the assignment. Once the moderator grades your submission, you'll find the details here. Feel free to make edits to your submission if needed.") }}
-
- {% if is_moderator %}
-
-
- {{ _("Student Name") }}
-
- {{ submission.member_name }}
-
- {% endif %}
- {% endif %}
-
-
-
- {{ _("Question")}}
-
- {{ assignment.question }}
-
-
- {% if assignment.type not in ["URL", "Text"] %}
-
-
- {{ _("Submit")}}
-
-
- {{ _("Upload assignment as {0}").format(assignment.type) }}
-
-
-
-
- {{ _("Browse").format(assignment.type) }}
-
-
-
- {{ _("Clear") }}
-
-
- {% else %}
-
-
-
- {{ _("Submission")}}
-
-
- {% if assignment.type == "URL" %}
- {{ _("Enter a {0}").format(assignment.type) }}
- {% else %}
- {{ _("Enter your response") }}
- {% endif %}
-
- {% if assignment.type == "URL" %}
-
- {% else %}
-
- {% if submission.answer %}
-
- {{ submission.answer }}
-
- {% endif %}
- {% endif %}
-
- {% endif %}
-
- {% if assignment.show_answer and submission %}
-
-
- {{ _("Response by Instructor:") }}
-
-
- {{ assignment.answer }}
-
-
- {% endif %}
-
- {% if assignment.grade_assignment and is_moderator %}
-
-
- {{ _("Status") }}
-
-
-
-
-
-
- {{ _("Comments by Mentor") }}
-
-
-
- {% endif %}
-
- {% if submission and submission.member == frappe.session.user and submission.comments %}
-
-
- {{ _("Comments by Mentor") }}
-
-
- {{ submission.comments }}
-
-
- {% endif %}
-
-
-{% endmacro %}
\ No newline at end of file
diff --git a/lms/www/assignment_submission/assignment_submission.js b/lms/www/assignment_submission/assignment_submission.js
deleted file mode 100644
index f336abc3..00000000
--- a/lms/www/assignment_submission/assignment_submission.js
+++ /dev/null
@@ -1,132 +0,0 @@
-frappe.ready(() => {
- if ($(".assignment-text").length) {
- frappe.require("controls.bundle.js", () => {
- make_text_editor();
- });
- }
-
- $(".btn-upload").click((e) => {
- upload_file(e);
- });
-
- $(".btn-save-assignment").click((e) => {
- save_assignment(e);
- });
-
- $(".btn-close").click((e) => {
- clear_preview(e);
- });
-});
-
-const upload_file = (e) => {
- let type = $(e.currentTarget).data("type");
- let mapper = {
- Image: ["image/*"],
- Document: [
- ".doc",
- ".docx",
- ".xml",
- "application/msword",
- "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
- ],
- PDF: [".pdf"],
- };
-
- new frappe.ui.FileUploader({
- disable_file_browser: true,
- folder: "Home/Attachments",
- make_attachments_public: true,
- restrictions: {
- allowed_file_types: mapper[type],
- },
- on_success: (file_doc) => {
- $(e.currentTarget).addClass("hide");
- $("#assignment-preview").removeClass("hide");
- $("#assignment-preview .btn-close").removeClass("hide");
- $("#assignment-preview a").attr(
- "href",
- encodeURI(file_doc.file_url)
- );
- $("#assignment-preview a").text(file_doc.file_url);
- },
- });
-};
-
-const save_assignment = (e) => {
- let data = $(e.currentTarget).data("type");
- let answer,
- file = "";
-
- if (data == "URL") {
- answer = $(".assignment-answer").val();
- if (!answer) {
- frappe.throw({
- title: __("No Submission"),
- message: __("Please enter a response."),
- });
- }
- } else if (data == "Text") {
- answer = this.text_editor.get_value("assignment_text");
- if (!answer) {
- frappe.throw({
- title: __("No Submission"),
- message: __("Please enter a response."),
- });
- }
- } else {
- file = $("#assignment-preview a").attr("href");
- if (!file) {
- frappe.throw({
- title: __("No File"),
- message: __("Please upload a file."),
- });
- }
- }
-
- frappe.call({
- method: "lms.lms.doctype.lms_assignment_submission.lms_assignment_submission.upload_assignment",
- args: {
- assignment: $(e.currentTarget).data("assignment"),
- submission: $(e.currentTarget).data("submission") || "",
- assignment_attachment: file,
- answer: answer,
- status: $("#status").val(),
- comments: $("#comments").val(),
- },
- callback: (data) => {
- frappe.show_alert({
- message: __("Saved"),
- indicator: "green",
- });
- setTimeout(() => {
- window.location.href = `/assignment-submission/${$(
- e.currentTarget
- ).data("assignment")}/${data.message}`;
- }, 2000);
- },
- });
-};
-
-const clear_preview = (e) => {
- $(".btn-upload").removeClass("hide");
- $("#assignment-preview").addClass("hide");
- $("#assignment-preview a").attr("href", "");
- $("#assignment-preview .btn-close").addClass("hide");
-};
-
-const make_text_editor = () => {
- this.text_editor = new frappe.ui.FieldGroup({
- fields: [
- {
- fieldname: "assignment_text",
- fieldtype: "Text Editor",
- default: $(".assignment-text-data").html(),
- },
- ],
- body: $(".assignment-text").get(0),
- });
- this.text_editor.make();
- $(".assignment-text .form-section:last").removeClass("empty-section");
- $(".assignment-text .frappe-control").removeClass("hide-control");
- $(".assignment-text .form-column").addClass("p-0");
-};
diff --git a/lms/www/assignment_submission/assignment_submission.py b/lms/www/assignment_submission/assignment_submission.py
deleted file mode 100644
index d1631a88..00000000
--- a/lms/www/assignment_submission/assignment_submission.py
+++ /dev/null
@@ -1,48 +0,0 @@
-import frappe
-from frappe import _
-from lms.lms.utils import has_course_moderator_role
-
-
-def get_context(context):
- context.no_cache = 1
-
- if frappe.session.user == "Guest":
- raise frappe.PermissionError(_("Please login to submit the assignment."))
-
- context.is_moderator = has_course_moderator_role()
- submission = frappe.form_dict["submission"]
- assignment = frappe.form_dict["assignment"]
-
- context.assignment = frappe.db.get_value(
- "LMS Assignment",
- assignment,
- ["title", "name", "type", "question", "show_answer", "answer", "grade_assignment"],
- as_dict=1,
- )
-
- if submission == "new-submission":
- context.submission = frappe._dict()
- else:
- context.submission = frappe.db.get_value(
- "LMS Assignment Submission",
- submission,
- [
- "name",
- "assignment_attachment",
- "answer",
- "comments",
- "status",
- "member",
- "member_name",
- ],
- as_dict=True,
- )
-
- if not context.submission:
- raise frappe.PermissionError(_("Invalid Submission URL"))
-
- if not context.is_moderator and frappe.session.user != context.submission.member:
- raise frappe.PermissionError(_("You don't have permission to access this page."))
-
- if not context.assignment or not context.submission:
- raise frappe.PermissionError(_("Invalid Submission URL"))
diff --git a/lms/www/assignments/assignment.html b/lms/www/assignments/assignment.html
deleted file mode 100644
index ee9a66a8..00000000
--- a/lms/www/assignments/assignment.html
+++ /dev/null
@@ -1,99 +0,0 @@
-{% extends "lms/templates/lms_base.html" %}
-{% block title %}
- {{ assignment.title if assignment.name else _("Assignment Details") }}
-{% endblock %}
-
-{% block page_content %}
-
- {{ Header() }}
-
- {{ AssignmentForm(assignment) }}
-
-
-{% endblock %}
-
-{% macro Header() %}
-
-{% endmacro %}
-
-{% macro AssignmentForm(assignment) %}
-
-
-
-
{{ _("Title") }}
-
- {{ _("Give the assignment a title.") }}
-
-
-
-
-
-
{{ "Type" }}
-
- {{ _("Select the format in which students will have to submit the assignment.") }}
-
-
-
-
-
-
-
- {{ _("Question") }}
-
-
- {{ _("Enter an assignment question.") }}
-
-
- {% if assignment.question %}
-
- {{ assignment.question }}
-
- {% endif %}
-
-
-
-{% endmacro %}
-
-
-{%- block script %}
- {{ super() }}
- {{ include_script('controls.bundle.js') }}
-{% endblock %}
\ No newline at end of file
diff --git a/lms/www/assignments/assignment.js b/lms/www/assignments/assignment.js
deleted file mode 100644
index 1d55034e..00000000
--- a/lms/www/assignments/assignment.js
+++ /dev/null
@@ -1,47 +0,0 @@
-frappe.ready(() => {
- if ($("#question").length) {
- make_editor();
- }
-
- $(".btn-save-assignment").click((e) => {
- save_assignment(e);
- });
-});
-
-const make_editor = () => {
- this.question = new frappe.ui.FieldGroup({
- fields: [
- {
- fieldname: "question",
- fieldtype: "Text Editor",
- default: $("#question-data").html(),
- },
- ],
- body: $("#question").get(0),
- });
- this.question.make();
- $("#question .form-section:last").removeClass("empty-section");
- $("#question .frappe-control").removeClass("hide-control");
- $("#question .form-column").addClass("p-0");
-};
-
-const save_assignment = (e) => {
- frappe.call({
- method: "lms.lms.doctype.lms_assignment.lms_assignment.save_assignment",
- args: {
- assignment: $(e.currentTarget).data("assignment") || "",
- title: $("#title").val(),
- question: this.question.fields_dict["question"].value,
- type: $("#type").val(),
- },
- callback: (data) => {
- frappe.show_alert({
- message: __("Saved"),
- indicator: "green",
- });
- setTimeout(() => {
- window.location.href = `/assignments/${data.message}`;
- }, 2000);
- },
- });
-};
diff --git a/lms/www/assignments/assignment.py b/lms/www/assignments/assignment.py
deleted file mode 100644
index ec8cc543..00000000
--- a/lms/www/assignments/assignment.py
+++ /dev/null
@@ -1,23 +0,0 @@
-import frappe
-from frappe import _
-from lms.lms.utils import has_course_moderator_role, has_course_instructor_role
-
-
-def get_context(context):
- context.no_cache = 1
-
- if not has_course_moderator_role() or not has_course_instructor_role():
- 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))
-
- assignment = frappe.form_dict["assignment"]
-
- if assignment == "new-assignment":
- context.assignment = frappe._dict()
- else:
- context.assignment = frappe.db.get_value(
- "LMS Assignment", assignment, ["title", "name", "type", "question"], as_dict=1
- )
diff --git a/lms/www/assignments/index.html b/lms/www/assignments/index.html
deleted file mode 100644
index 52374455..00000000
--- a/lms/www/assignments/index.html
+++ /dev/null
@@ -1,90 +0,0 @@
-{% extends "templates/base.html" %}
-{% block title %}
- {{ _("Assignment List") }}
-{% endblock %}
-
-{% block content %}
-
-
- {{ Header() }}
- {% if assignments | length %}
- {{ AssignmentList(assignments) }}
- {% else %}
- {{ EmptyState() }}
- {% endif %}
-
-
-{% endblock %}
-
-{% macro Header() %}
-
-{% endmacro %}
-
-{% macro AssignmentList(assignments) %}
-
-{% endmacro %}
-
-{% macro EmptyState() %}
-
-
-
-
- {{ _("You have not created any assignment yet.") }}
-
-
- {{ _("Create an assignment and evaluate your students.") }}
-
-
-
-{% endmacro %}
diff --git a/lms/www/assignments/index.py b/lms/www/assignments/index.py
deleted file mode 100644
index f8d9e3a4..00000000
--- a/lms/www/assignments/index.py
+++ /dev/null
@@ -1,17 +0,0 @@
-import frappe
-from lms.lms.utils import has_course_moderator_role
-
-
-def get_context(context):
- context.no_cache = 1
-
- filters = {"owner": frappe.session.user}
-
- if has_course_moderator_role():
- filters = {}
-
- context.assignments = frappe.get_all(
- "LMS Assignment",
- filters,
- ["title", "name", "type", "question"],
- )
diff --git a/lms/www/batch/__pycache__/__init__.py b/lms/www/batch/__pycache__/__init__.py
deleted file mode 100644
index e69de29b..00000000
diff --git a/lms/www/batch/edit.html b/lms/www/batch/edit.html
deleted file mode 100644
index b75ddbe1..00000000
--- a/lms/www/batch/edit.html
+++ /dev/null
@@ -1,134 +0,0 @@
-{% extends "lms/templates/lms_base.html" %}
-
-{% block title %}
-{% if lesson.title %}
-{{ lesson.title }} - {{ course.title }}
-{% else %}
-{{ _("New Lesson") }}
-{% endif %}
-{% endblock %}
-
-{% block page_content %}
-
- {{ Header() }}
-
- {{ CreateLesson() }}
-
-
-{% endblock %}
-
-
-{% macro Header() %}
-
-{% endmacro %}
-
-{% macro CreateLesson() %}
-
-
-
- {{ _("Title") }}
-
-
-
-
-
-
-
-
-
- {{ _("Show preview of this lesson to Guest users.") }}
-
-
-
-
-
-
-
-
-
- {{ _("Instructor Notes") }}
-
-
- {{ _("These notes will only be visible to the Course Creator, Course Evaluaor and Moderator.") }}
-
-
-
- {% if lesson.instructor_notes %}
-
{{ lesson.instructor_notes }}
- {% endif %}
-
-
-
-
-
- {{ _("Content") }}
-
-
- {{ _("Add your lesson content here") }}
-
-
-
-
-
- {% if lesson.body %}
-
{{ lesson.body }}
- {% endif %}
-
-
-
-{% endmacro %}
-
-
-{%- block script %}
- {{ super() }}
-
-
-
-
-{% endblock %}
-
diff --git a/lms/www/batch/edit.js b/lms/www/batch/edit.js
deleted file mode 100644
index d9e2d892..00000000
--- a/lms/www/batch/edit.js
+++ /dev/null
@@ -1,532 +0,0 @@
-frappe.ready(() => {
- let self = this;
- frappe.require("controls.bundle.js");
- frappe.telemetry.capture("on_lesson_creation_page", "lms");
-
- if ($("#current-lesson-content").length) {
- parse_string_to_lesson("lesson");
- }
-
- if ($("#current-instructor-notes").length) {
- parse_string_to_lesson("notes");
- }
-
- setup_editor_for_lesson_content();
- setup_editor_for_instructor_notes();
-
- $("#save-lesson").click((e) => {
- save_lesson(e);
- });
-});
-
-const setup_editor_for_lesson_content = () => {
- self.editor = new EditorJS({
- holder: "lesson-content",
- tools: get_tools(),
- data: {
- blocks: self.lesson_blocks || [],
- },
- });
-};
-
-const setup_editor_for_instructor_notes = () => {
- self.instructor_notes_editor = new EditorJS({
- holder: "instructor-notes",
- tools: get_tools(),
- data: {
- blocks: self.notes_blocks || [],
- },
- });
-};
-
-const get_tools = () => {
- return {
- embed: {
- class: Embed,
- config: {
- services: {
- youtube: true,
- vimeo: true,
- codepen: true,
- slides: {
- regex: /https:\/\/docs\.google\.com\/presentation\/d\/e\/([A-Za-z0-9_-]+)\/pub/,
- embedUrl:
- "https://docs.google.com/presentation/d/e/<%= remote_id %>/embed",
- html: "
",
- },
- },
- },
- },
- header: {
- class: Header,
- inlineToolbar: ["bold", "italic", "link"],
- config: {
- levels: [4, 5, 6],
- defaultLevel: 5,
- },
- icon: `
-
- `,
- },
- paragraph: {
- class: Paragraph,
- inlineToolbar: true,
- config: {
- preserveBlank: true,
- },
- },
- youtube: YouTubeVideo,
- quiz: Quiz,
- upload: Upload,
- };
-};
-
-const parse_string_to_lesson = (type) => {
- let content;
- let blocks = [];
-
- if (type == "lesson") {
- content = $("#current-lesson-content").html();
- } else if (type == "notes") {
- content = $("#current-instructor-notes").html();
- }
-
- content.split("\n").forEach((block) => {
- if (block.includes("{{ YouTubeVideo")) {
- let youtube_id = block.match(/\(["']([^"']+?)["']\)/)[1];
- blocks.push({
- type: "youtube",
- data: {
- youtube: youtube_id,
- },
- });
- } else if (block.includes("{{ Quiz")) {
- let quiz = block.match(/\(["']([^"']+?)["']\)/)[1];
- blocks.push({
- type: "quiz",
- data: {
- quiz: quiz,
- },
- });
- } else if (block.includes("{{ Video")) {
- let video = block.match(/\(["']([^"']+?)["']\)/)[1];
- blocks.push({
- type: "upload",
- data: {
- file_url: video,
- file_type: "video",
- },
- });
- } else if (block.includes("{{ Audio")) {
- let audio = block.match(/\(["']([^"']+?)["']\)/)[1];
- blocks.push({
- type: "upload",
- data: {
- file_url: audio,
- file_type: "audio",
- },
- });
- } else if (block.includes("{{ PDF")) {
- let pdf = block.match(/\(["']([^"']+?)["']\)/)[1];
- blocks.push({
- type: "upload",
- data: {
- file_url: pdf,
- file_type: "pdf",
- },
- });
- } else if (block.includes("{{ Embed")) {
- let embed = block.match(/\(["']([^"']+?)["']\)/)[1];
- blocks.push({
- type: "embed",
- data: {
- service: embed.split("|||")[0],
- embed: embed.split("|||")[1],
- },
- });
- } else if (block.includes("![]")) {
- let image = block.match(/\((.*?)\)/)[1];
- blocks.push({
- type: "upload",
- data: {
- file_url: image,
- file_type: "image",
- },
- });
- } else if (block.includes("#")) {
- let level = (block.match(/#/g) || []).length;
- blocks.push({
- type: "header",
- data: {
- text: block.replace(/#/g, "").trim(),
- level: level,
- },
- });
- } else {
- blocks.push({
- type: "paragraph",
- data: {
- text: block,
- },
- });
- }
- });
-
- if (type == "lesson") {
- this.lesson_blocks = blocks;
- } else if (type == "notes") {
- this.notes_blocks = blocks;
- }
-};
-
-const save_lesson = (e) => {
- self.editor.save().then((outputData) => {
- parse_content_to_string(outputData, "lesson");
-
- self.instructor_notes_editor.save().then((outputData) => {
- parse_content_to_string(outputData, "notes");
- save();
- });
- });
-};
-
-const parse_content_to_string = (data, type) => {
- let lesson_content = "";
- data.blocks.forEach((block) => {
- if (block.type == "youtube") {
- lesson_content += `{{ YouTubeVideo("${block.data.youtube}") }}\n`;
- } else if (block.type == "quiz") {
- lesson_content += `{{ Quiz("${block.data.quiz}") }}\n`;
- } else if (block.type == "upload") {
- let url = block.data.file_url;
- if (block.data.file_type == "video") {
- lesson_content += `{{ Video("${url}") }}\n`;
- } else if (block.data.file_type == "audio") {
- lesson_content += `{{ Audio("${url}") }}\n`;
- } else if (block.data.file_type == "pdf") {
- lesson_content += `{{ PDF("${url}") }}\n`;
- } else {
- lesson_content += ``;
- }
- } else if (block.type == "header") {
- lesson_content +=
- "#".repeat(block.data.level) + ` ${block.data.text}\n`;
- } else if (block.type == "paragraph") {
- lesson_content += `${block.data.text}\n`;
- } else if (block.type == "embed") {
- lesson_content += `{{ Embed("${
- block.data.service
- }|||${block.data.embed.replace(/&/g, "&")}") }}\n`;
- }
- });
- if (type == "lesson") {
- this.lesson_content_data = lesson_content;
- } else if (type == "notes") {
- this.instructor_notes_data = lesson_content;
- }
-};
-
-const save = () => {
- validate_mandatory(this.lesson_content_data);
- let lesson = $("#lesson-title").data("lesson");
- frappe.call({
- method: "lms.lms.doctype.lms_course.lms_course.save_lesson",
- args: {
- title: $("#lesson-title").val(),
- body: this.lesson_content_data,
- chapter: decodeURIComponent($("#lesson-title").data("chapter")),
- preview: $("#preview").prop("checked") ? 1 : 0,
- idx: $("#lesson-title").data("index"),
- lesson: lesson ? lesson : "",
- instructor_notes: this.instructor_notes_data,
- },
- callback: (data) => {
- frappe.show_alert({
- message: __("Saved"),
- indicator: "green",
- });
- setTimeout(() => {
- window.location.href = window.location.href.split("?")[0];
- }, 1000);
- },
- });
-};
-
-const validate_mandatory = (lesson_content) => {
- if (!$("#lesson-title").val()) {
- let error = $("p")
- .addClass("error-message")
- .text(__("Please enter a Lesson Title"));
- $(error).insertAfter("#lesson-title");
- $("#lesson-title").focus();
- throw "Title is mandatory";
- }
-
- if (!lesson_content.trim()) {
- let error = $("p")
- .addClass("error-message")
- .text(__("Please enter some content for the lesson"));
- $(error).insertAfter("#lesson-content");
- document
- .getElementById("lesson-content")
- .scrollIntoView({ block: "start" });
- throw "Lesson Content is mandatory";
- }
-};
-
-const get_file_type = (url) => {
- let video_types = ["mov", "mp4", "mkv"];
- let video_extension = url.split(".").pop();
-
- if (video_types.indexOf(video_extension) >= 0) {
- return "video";
- }
-
- let audio_types = ["mp3", "wav", "ogg"];
- let audio_extension = url.split(".").pop();
-
- if (audio_types.indexOf(audio_extension) >= 0) {
- return "audio";
- }
-
- if (url.split(".").pop() == "pdf") {
- return "pdf";
- }
-
- return "image";
-};
-
-class YouTubeVideo {
- constructor({ data }) {
- this.data = data;
- }
-
- static get toolbox() {
- return {
- title: "YouTube Video",
- icon: `
`,
- };
- }
-
- render() {
- this.wrapper = document.createElement("div");
- if (this.data && this.data.youtube) {
- $(this.wrapper).html(this.render_youtube(this.data.youtube));
- } else {
- this.render_youtube_dialog();
- }
- return this.wrapper;
- }
-
- render_youtube_dialog() {
- let me = this;
- let youtubedialog = new frappe.ui.Dialog({
- title: __("YouTube Video"),
- fields: [
- {
- fieldname: "youtube",
- fieldtype: "Data",
- label: __("YouTube Video ID"),
- reqd: 1,
- },
- {
- fieldname: "instructions_section_break",
- fieldtype: "Section Break",
- label: __("Instructions:"),
- },
- {
- fieldname: "instructions",
- fieldtype: "HTML",
- label: __("Instructions"),
- options: __(
- "Enter the YouTube Video ID. The ID is the part of the URL after
watch?v=. For example, if the URL is
https://www.youtube.com/watch?v=QH2-TGUlwu4, the ID is
QH2-TGUlwu4"
- ),
- },
- ],
- primary_action_label: __("Insert"),
- primary_action(values) {
- youtubedialog.hide();
- me.youtube = values.youtube;
- $(me.wrapper).html(me.render_youtube(values.youtube));
- },
- });
- youtubedialog.show();
- }
-
- render_youtube(youtube) {
- return `
VIDEO `;
- }
-
- validate(savedData) {
- return !savedData.youtube || !savedData.youtube.trim() ? false : true;
- }
-
- save(block_content) {
- return {
- youtube: this.data.youtube || this.youtube,
- };
- }
-}
-
-class Quiz {
- static get toolbox() {
- return {
- title: "Quiz",
- icon: `
`,
- };
- }
-
- constructor({ data }) {
- this.data = data;
- }
-
- render() {
- this.wrapper = document.createElement("div");
- if (this.data && this.data.quiz) {
- $(this.wrapper).html(this.render_quiz(this.data.quiz));
- } else {
- this.render_quiz_dialog();
- }
- return this.wrapper;
- }
-
- render_quiz_dialog() {
- let me = this;
- let quizdialog = new frappe.ui.Dialog({
- title: __("Manage Quiz"),
- fields: [
- {
- fieldname: "quiz",
- fieldtype: "Link",
- label: __("Quiz"),
- options: "LMS Quiz",
- only_select: 1,
- },
- ],
- primary_action_label: __("Insert"),
- primary_action(values) {
- me.quiz = values.quiz;
- quizdialog.hide();
- $(me.wrapper).html(me.render_quiz(me.quiz));
- },
- secondary_action_label: __("Create New"),
- secondary_action: () => {
- window.location.href = `/quizzes`;
- },
- });
- quizdialog.show();
- setTimeout(() => {
- $(".modal-body").css("min-height", "200px");
- $(".modal-body input").focus();
- }, 1000);
- }
-
- render_quiz(quiz) {
- return `
- Quiz: ${quiz}
- `;
- }
-
- validate(savedData) {
- return !savedData.quiz || !savedData.quiz.trim() ? false : true;
- }
-
- save(block_content) {
- return {
- quiz: this.data.quiz || this.quiz,
- };
- }
-}
-
-class Upload {
- static get toolbox() {
- return {
- title: "Upload",
- icon: `
`,
- };
- }
-
- constructor({ data }) {
- this.data = data;
- }
-
- render() {
- this.wrapper = document.createElement("div");
- if (this.data && this.data.file_url) {
- $(this.wrapper).html(this.render_upload(this.data.file_url));
- } else {
- this.render_upload_dialog();
- }
- return this.wrapper;
- }
-
- render_upload_dialog() {
- let self = this;
- new frappe.ui.FileUploader({
- disable_file_browser: true,
- folder: "Home/Attachments",
- make_attachments_public: true,
- restrictions: {
- allowed_file_types: ["image/*", "video/*", "audio/*", ".pdf"],
- },
- on_success: (file_doc) => {
- self.file_url = file_doc.file_url;
- $(self.wrapper).html(self.render_upload(self.file_url));
- },
- });
- }
-
- render_upload(url) {
- this.file_type = get_file_type(url);
- if (this.file_type == "video") {
- return `
-
- `;
- } else if (this.file_type == "audio") {
- return `
-
- `;
- } else if (this.file_type == "pdf") {
- return `
`;
- } else {
- return `
`;
- }
- }
-
- validate(savedData) {
- return !savedData.file_url || !savedData.file_url.trim() ? false : true;
- }
-
- save(block_content) {
- return {
- file_url: this.data.file_url || this.file_url,
- file_type: this.file_type,
- };
- }
-}
-
-const make_instructor_notes_component = () => {
- this.instructor_notes = new frappe.ui.FieldGroup({
- fields: [
- {
- fieldname: "instructor_notes",
- fieldtype: "Text",
- default: $("#current-instructor-notes").html(),
- },
- ],
- body: $("#instructor-notes").get(0),
- });
- this.instructor_notes.make();
- $("#instructor-notes .form-section:last").removeClass("empty-section");
- $("#instructor-notes .frappe-control").removeClass("hide-control");
- $("#instructor-notes .form-column").addClass("p-0");
-};
diff --git a/lms/www/batch/edit.py b/lms/www/batch/edit.py
deleted file mode 100644
index 88256179..00000000
--- a/lms/www/batch/edit.py
+++ /dev/null
@@ -1,22 +0,0 @@
-import frappe
-from lms.www.utils import get_current_lesson_details, get_common_context
-from lms.lms.utils import is_instructor, has_course_moderator_role
-from frappe import _
-
-
-def get_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.lesson_number = lesson_number
- context.chapter = frappe.db.get_value(
- "Chapter Reference", {"idx": chapter_index, "parent": context.course.name}, "chapter"
- )
- context.lesson = get_current_lesson_details(lesson_number, context, True)
- context.is_moderator = has_course_moderator_role()
- instructor = is_instructor(context.course.name)
-
- if not instructor and not has_course_moderator_role():
- raise frappe.PermissionError(_("You do not have permission to access this page."))
diff --git a/lms/www/batch/join.html b/lms/www/batch/join.html
deleted file mode 100644
index 3377ebce..00000000
--- a/lms/www/batch/join.html
+++ /dev/null
@@ -1,72 +0,0 @@
-% extends "templates/base.html" %}
-{% block title %}Join a Course{% endblock %}
-
-{% block head_include %}
-
-
-{% endblock %}
-
-{% block content %}
-{% if frappe.session.user == "Guest" %}
-
-
-
- {{ _("Login Required") }}
-
-
{{ _("Please log in to confirm joining the course" )}} {{ batch.course_title }}.
-
{{_("Login")}}
-
-
-{% elif already_a_member %}
-
-
-
- {{ _("Already a member") }}
-
-
{{ _("You are already a member of the batch") }} {{ batch.title }} {{ _("for the course") }} {{ batch.course_title }}.
-
-
{{_("Go to Batch Home")}}
-
-
-{% else %}
-
-
-
- {{ _("Confirm your membership") }}
-
-
{{ _("Please provide your confirmation to be a part of the batch") }} {{ batch.title }} {{ _("for the course") }}
- {{ batch.course_title }}.
-
-
{{_("Confirm")}}
-
-
-{% endif %}
-{% endblock %}
-
-{% block script %}
-
-{% endblock %}
diff --git a/lms/www/batch/join.py b/lms/www/batch/join.py
deleted file mode 100644
index 06a59766..00000000
--- a/lms/www/batch/join.py
+++ /dev/null
@@ -1,11 +0,0 @@
-import frappe
-
-
-def get_context(context):
- context.no_cache = 1
- batch_name = frappe.form_dict["batch"]
- context.batch_old = frappe.get_doc("LMS Batch Old", batch_name)
- context.already_a_member = context.batch_old.is_member(frappe.session.user)
- context.batch_old.course_title = frappe.db.get_value(
- "LMS Course", context.batch_old.course, "title"
- )
diff --git a/lms/www/batch/learn.html b/lms/www/batch/learn.html
deleted file mode 100644
index 48c8376e..00000000
--- a/lms/www/batch/learn.html
+++ /dev/null
@@ -1,265 +0,0 @@
-{% extends "lms/templates/lms_base.html" %}
-{% from "www/macros/livecode.html" import LiveCodeEditorJS, LiveCodeEditor with context %}
-
-
-{% block title %}
-{{ lesson.title }} - {{ course.title }}
-{% endblock %}
-
-
-{% block head_include %}
-
-
-{% for ext in page_extensions %}
-{{ ext.render_header() }}
-{% endfor %}
-{% endblock %}
-
-
-{% block page_content %}
-
-
-
-
-
-
-
- {{ course.title }}
-
-
- {% if membership %}
-
-
{{ progress }}% {{ _("Completed") }}
-
-
- {% endif %}
-
-
- {% set classname = class_info.name if class_info else False %}
- {{ widgets.CourseOutline(course=course, membership=membership, lesson_page=True, classname=classname) }}
-
-
-
- {{ BreadCrumb(course, lesson, class_info) }}
- {{ LessonContent(lesson, class_info) }}
- {% if course.status == "Approved" and not course.upcoming and not class_info %}
- {{ Discussions() }}
- {% endif %}
-
-
-
-
-{% endblock %}
-
-
-
-{% macro BreadCrumb(course, lesson, class_info) %}
-
-{% endmacro %}
-
-
-
-{% macro LessonContent(lesson, class_info) %}
-{% set instructors = get_instructors(course.name) %}
-{% set is_instructor = is_instructor(course.name) %}
-
-
-
-
- {% if get_progress(course.name, lesson.name) == 'Complete' %}
-
{{ _("COMPLETED") }}
- {% endif %}
-
-
- {% if (is_instructor or has_course_moderator_role()) %}
-
- {{ _("Edit") }}
-
- {% endif %}
-
-
-
{% if lesson.title %}{{ lesson.title }}{% endif %}
-
-
-
-
-
-
-
- {% if show_lesson %}
-
- {% if is_instructor and not lesson.include_in_preview %}
-
- {{ _("This lesson is not available for preview. As you are the Instructor of the course only you can see it.") }}
-
×
-
- {% endif %}
-
- {% if instructor_notes and (is_moderator or instructor or is_evaluator) %}
-
-
-
-
-
-
- {{ _("Instructor Notes") }}
-
-
-
- {{ instructor_notes }}
-
-
- {% endif %}
-
- {{ render_html(lesson) }}
-
- {% else %}
- {% set course_link = "
" + _('here') + " " %}
-
- {{ _("There is no preview available for this lesson.
- Please join the course to access it.
- Click {0} to enroll.").format(course_link) }}
-
- {% endif %}
-
-
- {% if not class_info %}
- {{ pagination(prev_url, next_url) }}
- {% endif %}
-
-
-{% endmacro %}
-
-
-
-{% macro pagination(prev_url, next_url) %}
- {% if prev_url or next_url %}
-
- {% endif %}
-{% endmacro %}
-
-{% macro UploadAttachments() %}
-
-
-
-
-
-
- 0 {{ _("attachments") }}
-
-
-
-
-
-
- {{ _("Upload Attachments") }}
-
-
-
-
-
-{% endmacro %}
-
-
-{% macro Discussions() %}
- {% set topics_count = frappe.db.count("Discussion Topic", {
- "reference_doctype": "Course Lesson",
- "reference_docname": lesson.name
- }) %}
- {% set condition = is_instructor(course.name) or membership %}
- {% set doctype, docname = _("Course Lesson"), lesson.name %}
- {% set title = "Questions" if topics_count else "" %}
- {% set cta_title = "Ask a Question" %}
- {% set button_name = _("Start Learning") %}
- {% set redirect_to = "/courses/" + course.name %}
- {% set empty_state_title = _("Have a doubt?") %}
- {% set empty_state_subtitle = _("Post it here, our mentors will help you out.") %}
-
- {% include "frappe/templates/discussions/discussions_section.html" %}
-
-{% endmacro %}
-
-
-{%- block script %}
- {{ super() }}
- {{ include_script('controls.bundle.js') }}
-
- {% for ext in page_extensions %}
- {{ ext.render_footer() }}
- {% endfor %}
-{%- endblock %}
diff --git a/lms/www/batch/learn.js b/lms/www/batch/learn.js
deleted file mode 100644
index f7cf6a94..00000000
--- a/lms/www/batch/learn.js
+++ /dev/null
@@ -1,253 +0,0 @@
-frappe.ready(() => {
- this.marked_as_complete = false;
- let self = this;
-
- frappe.telemetry.capture("on_lesson_page", "lms");
-
- fetch_assignments();
-
- save_current_lesson();
-
- $(window).scroll(() => {
- let self = this;
- if (
- !$("#status-indicator").length &&
- !self.marked_as_complete &&
- $(".title").hasClass("is-member")
- ) {
- self.marked_as_complete = true;
- mark_progress();
- }
- });
-
- $("#certification").click((e) => {
- create_certificate(e);
- });
-
- $(".submit-work").click((e) => {
- attach_work(e);
- });
-
- $(".clear-work").click((e) => {
- clear_work(e);
- });
-
- $(".btn-back").click((e) => {
- window.location.href = window.location.href.split("?")[0];
- });
-
- $(document).on("click", ".copy-link", (e) => {
- frappe.utils.copy_to_clipboard($(e.currentTarget).data("link"));
- $(".attachments").collapse("hide");
- });
-});
-
-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"),
- });
- }
-};
-
-const mark_progress = () => {
- 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,
- },
- callback: (data) => {
- if (data.message) {
- 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")
- ) {
- $("#certification").removeClass("hide");
- }
-};
-
-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,
- },
- 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");
- if (files && files.length) {
- 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();
-
- xhr.onreadystatechange = () => {
- if (xhr.readyState == XMLHttpRequest.DONE) {
- if (xhr.status === 200) {
- 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 || ""}`
- );
- } else if (xhr.status === 413) {
- frappe.msgprint(
- __("Size exceeds the maximum allowed file size.")
- );
- } else {
- 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);
-
- let form_data = new FormData();
- if (file.file_obj) {
- 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.lms_assignment_submission.lms_assignment_submission.upload_assignment",
- args: {
- assignment_attachment: file.file_url,
- lesson: $(".title").attr("data-lesson"),
- submission: $(".preview-work").data("submission") || "",
- },
- 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.addClass("hide");
- },
- });
-};
-
-const return_as_dataurl = (files) => {
- 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);
- })
- );
- return Promise.all(promises);
-};
-
-const add_files = (files) => {
- files = Array.from(files).map((file) => {
- let is_image = file.type.startsWith("image");
- return {
- file_obj: file,
- cropper_file: file,
- crop_box_data: null,
- optimize: this.attach_doc_image ? true : false,
- name: file.name,
- doc: null,
- progress: 0,
- total: 0,
- failed: false,
- request_succeeded: false,
- error_message: null,
- uploading: false,
- private: !is_image,
- };
- });
- return files;
-};
-
-const clear_work = (e) => {
- const target = $(e.currentTarget);
- const parent = target.closest(".preview-work");
- parent.addClass("hide");
- parent.siblings(".attach-file").removeClass("hide").val(null);
- parent.siblings(".submit-work").removeClass("hide");
-};
-
-const fetch_assignments = () => {
- if ($(".attach-file").length <= 0) return;
- frappe.call({
- method: "lms.lms.doctype.lms_assignment_submission.lms_assignment_submission.get_assignment",
- args: {
- lesson: $(".title").attr("data-lesson"),
- },
- callback: (data) => {
- if (data.message) {
- const assignment = data.message;
- const status = assignment.status;
- let target = $(".attach-file");
- target.addClass("hide");
- target.siblings(".submit-work").addClass("hide");
- target.siblings(".preview-work").removeClass("hide");
- if (status != "Not Graded") {
- let color = status == "Pass" ? "green" : "red";
- $(".assignment-status")
- .removeClass("hide")
- .addClass(color)
- .text(data.message.status);
- target.siblings(".alert").addClass("hide");
- $(".clear-work").addClass("hide");
- if (assignment.comments) {
- $(".comments").removeClass("hide");
- $(".comment").text(assignment.comments);
- }
- }
- target
- .siblings(".preview-work")
- .find("a")
- .attr("href", assignment.assignment_attachment)
- .text(assignment.file_name);
-
- target
- .siblings(".preview-work")
- .attr("data-submission", assignment.name);
- }
- },
- });
-};
diff --git a/lms/www/batch/learn.py b/lms/www/batch/learn.py
deleted file mode 100644
index d51751ac..00000000
--- a/lms/www/batch/learn.py
+++ /dev/null
@@ -1,119 +0,0 @@
-import frappe
-from frappe import _
-from frappe.utils import cstr, flt
-from lms.lms.md import markdown_to_html
-
-from lms.lms.utils import (
- get_lesson_url,
- has_course_moderator_role,
- is_instructor,
- has_course_evaluator_role,
-)
-from lms.www.utils import (
- get_common_context,
- redirect_to_lesson,
- get_current_lesson_details,
-)
-
-
-def get_context(context):
- get_common_context(context)
-
- chapter_index = frappe.form_dict.get("chapter")
- lesson_index = frappe.form_dict.get("lesson")
- class_name = frappe.form_dict.get("class")
-
- if class_name:
- context.class_info = frappe._dict(
- {
- "name": class_name,
- "title": frappe.db.get_value("LMS Batch", class_name, "title"),
- }
- )
-
- lesson_number = f"{chapter_index}.{lesson_index}"
- context.lesson_number = lesson_number
- 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_)
-
- context.lesson = get_current_lesson_details(lesson_number, context)
- context.instructor = is_instructor(context.course.name)
- context.is_moderator = has_course_moderator_role()
- context.is_evaluator = has_course_evaluator_role()
-
- if context.lesson.instructor_notes:
- context.instructor_notes = markdown_to_html(context.lesson.instructor_notes)
-
- context.show_lesson = (
- context.membership
- or (context.lesson and context.lesson.include_in_preview)
- or context.instructor
- or context.is_moderator
- or context.is_evaluator
- )
-
- if not context.lesson:
- context.lesson = frappe._dict()
-
- if frappe.form_dict.get("edit"):
- if not context.instructor and not context.is_moderator:
- 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,
- }
-
- context.page_extensions = get_page_extensions(context)
- context.page_context = {
- "course": context.course.name,
- "batch_old": context.batch_old,
- "lesson": context.lesson.name if context.lesson.name else "New Lesson",
- "is_member": context.membership is not None,
- }
-
-
-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
- )
-
-
-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
-
-
-def get_neighbours(current, lessons):
- numbers = [lesson.number for lesson in lessons]
- tuples_list = [tuple(int(x) for x in s.split(".")) for s in numbers]
- sorted_tuples = sorted(tuples_list)
- sorted_numbers = [".".join(str(num) for num in t) for t in sorted_tuples]
- index = sorted_numbers.index(current)
-
- return {
- "prev": sorted_numbers[index - 1] if index - 1 >= 0 else None,
- "next": sorted_numbers[index + 1] if index + 1 < len(sorted_numbers) else None,
- }
diff --git a/lms/www/batch/quiz.html b/lms/www/batch/quiz.html
deleted file mode 100644
index 953e3496..00000000
--- a/lms/www/batch/quiz.html
+++ /dev/null
@@ -1,150 +0,0 @@
-{% extends "templates/base.html" %}
-{% block title %}
- {{ quiz.title if quiz.name else _("Quiz Details") }}
-{% endblock %}
-
-
-{% block content %}
-
- {{ Header() }}
-
- {{ QuizForm(quiz) }}
-
-
-{% endblock %}
-
-{% macro QuizForm(quiz) %}
-
-{% endmacro %}
-
-
-{% macro Header() %}
-
-{% endmacro %}
-
-{% macro QuizDetails(quiz) %}
-
-
-
-
- {{ _("Title") }}
-
-
- {{ _("Add a title for the quiz") }}
-
-
-
-
-
-
-
-
-
- {{ _("Max Attempts") }}
-
-
- {{ _("Enter the maximum number of times a user can attempt this quiz") }}
-
-
- {% set max_attempts = quiz.max_attempts if quiz.name else 0 %}
-
-
-
-
-
-
- {{ _("Passing Percentage") }}
-
-
- {{ _("Minimum percentage required to pass this quiz.") }}
-
-
-
-
-
-
-
- {% set show_answers = quiz.show_answers or not quiz.name %}
-
-
- {{ _("Show Answers") }}
-
-
-
- {{ _("Show Submission History") }}
-
-
-
-{% endmacro %}
-
-{% macro Question(question, index) %}
-{% set type = question.type if question.type else "Choices" %}
-
-
-
- {{ index }}.
-
- {{ question.question.split("\n")[0] }}
-
-
-{% endmacro %}
-
-{% macro EmptyState() %}
-
-
-
- {{ _("You have not added any question yet") }}
-
-
- {{ _("Create and manage questions from here.") }}
-
-
-
-
- {{ _("Add Question") }}
-
-
-
-
-
-{% endmacro %}
-
-{%- block script %}
- {{ super() }}
- {% if has_course_instructor_role() or has_course_moderator_role() %}
-
- {% endif %}
-{% endblock %}
\ No newline at end of file
diff --git a/lms/www/batch/quiz.js b/lms/www/batch/quiz.js
deleted file mode 100644
index 7774ad63..00000000
--- a/lms/www/batch/quiz.js
+++ /dev/null
@@ -1,307 +0,0 @@
-frappe.ready(() => {
- if ($(".questions-table").length) {
- frappe.require("controls.bundle.js", () => {
- create_questions_table();
- });
- }
-
- $(".btn-save-quiz").click((e) => {
- save_quiz();
- });
-
- $(".question-row").click((e) => {
- edit_question(e);
- });
-
- $(document).on("click", ".questions-table .link-btn", (e) => {
- e.preventDefault();
- fetch_question_data(e);
- });
-});
-
-const show_question_modal = (values = {}) => {
- let fields = get_question_fields(values);
-
- this.question_dialog = new frappe.ui.Dialog({
- title: __("Add Question"),
- fields: fields,
- primary_action: (data) => {
- if (values) data.name = values.name;
- save_question(data);
- },
- });
-
- question_dialog.show();
-};
-
-const get_question_fields = (values = {}) => {
- if (!values.question) values = {};
-
- let dialog_fields = [
- {
- fieldtype: "Text Editor",
- fieldname: "question",
- label: __("Question"),
- reqd: 1,
- default: values.question || "",
- },
- {
- fieldtype: "Select",
- fieldname: "type",
- label: __("Type"),
- options: ["Choices", "User Input"],
- default: values.type || "Choices",
- },
- ];
- Array.from({ length: 4 }, (x, i) => {
- num = i + 1;
-
- dialog_fields.push({
- fieldtype: "Section Break",
- fieldname: `section_break_${num}`,
- });
-
- let option = {
- fieldtype: "Small Text",
- fieldname: `option_${num}`,
- label: __("Option") + ` ${num}`,
- depends_on: "eval:doc.type=='Choices'",
- default: values[`option_${num}`] || "",
- };
-
- if (num <= 2) option.mandatory_depends_on = "eval:doc.type=='Choices'";
-
- dialog_fields.push(option);
- console.log(dialog_fields);
-
- dialog_fields.push({
- fieldtype: "Data",
- fieldname: `explanaion_${num}`,
- label: __("Explanation"),
- depends_on: "eval:doc.type=='Choices'",
- default: values[`explanaion_${num}`] || "",
- });
-
- let is_correct = {
- fieldtype: "Check",
- fieldname: `is_correct_${num}`,
- label: __("Is Correct"),
- depends_on: "eval:doc.type=='Choices'",
- default: values[`is_correct_${num}`] || 0,
- };
-
- if (num <= 2)
- is_correct.mandatory_depends_on = "eval:doc.type=='Choices'";
-
- dialog_fields.push(is_correct);
-
- possibility = {
- fieldtype: "Small Text",
- fieldname: `possibility_${num}`,
- label: __("Possible Answer") + ` ${num}`,
- depends_on: "eval:doc.type=='User Input'",
- default: values[`possibility_${num}`] || "",
- };
-
- if (num == 1)
- possibility.mandatory_depends_on = "eval:doc.type=='User Input'";
-
- dialog_fields.push(possibility);
- });
-
- return dialog_fields;
-};
-
-const edit_question = (e) => {
- let question = $(e.currentTarget).data("question");
- frappe.call({
- method: "lms.lms.doctype.lms_quiz.lms_quiz.get_question_details",
- args: {
- question: question,
- },
- callback: (data) => {
- if (data.message) show_question_modal(data.message);
- },
- });
-};
-
-const save_quiz = (values) => {
- validate_mandatory();
- validate_questions();
-
- frappe.call({
- method: "lms.lms.doctype.lms_quiz.lms_quiz.save_quiz",
- args: {
- quiz_title: $("#quiz-title").val(),
- max_attempts: $("#max-attempts").val(),
- passing_percentage: $("#passing-percentage").val(),
- quiz: $("#quiz-form").data("name") || "",
- questions: this.table.get_value("questions"),
- show_answers: $("#show-answers").is(":checked") ? 1 : 0,
- show_submission_history: $("#show-submission-history").is(
- ":checked"
- )
- ? 1
- : 0,
- },
- callback: (data) => {
- frappe.show_alert({
- message: __("Saved"),
- indicator: "green",
- });
- setTimeout(() => {
- window.location.href = `/quizzes/${data.message}`;
- }, 2000);
- },
- });
-};
-
-const validate_mandatory = () => {
- let fields = ["#quiz-title", "#passing-percentage"];
- fields.forEach((field, idx) => {
- if (!$(field).val()) {
- let error = $("p")
- .addClass("error-message")
- .text(__("Please enter a value"));
- $(error).insertAfter(field);
- scroll_to_element($(field));
- throw "This field is mandatory";
- }
- });
-};
-
-const validate_questions = () => {
- let questions = this.table.get_value("questions");
-
- if (!questions.length) {
- frappe.throw(__("Please add a question."));
- }
-
- questions.forEach((question, index) => {
- if (!question.question) {
- frappe.throw(__("Please add question in row") + " " + (index + 1));
- }
-
- if (!question.marks) {
- frappe.throw(__("Please add marks in row") + " " + (index + 1));
- }
- });
-};
-
-const scroll_to_element = (element) => {
- if ($(element).length) {
- $([document.documentElement, document.body]).animate(
- {
- scrollTop: $(element).offset().top - 100,
- },
- 1000
- );
- }
-};
-
-const save_question = (values) => {
- frappe.call({
- method: "lms.lms.doctype.lms_quiz.lms_quiz.save_question",
- args: {
- quiz: $("#quiz-form").data("name") || "",
- values: values,
- index: $("#quiz-form").data("index") + 1,
- },
- callback: (data) => {
- if (data.message) this.question_dialog.hide();
-
- if (values.name) {
- frappe.show_alert({
- message: __("Saved"),
- indicator: "green",
- });
- setTimeout(() => {
- window.location.reload();
- }, 1000);
- } else {
- let details = {
- question: data.message,
- };
- index = this.table.get_value("questions").length;
- add_question_row(details, index);
- }
- },
- });
-};
-
-const create_questions_table = () => {
- this.table = new frappe.ui.FieldGroup({
- fields: [
- {
- fieldname: "questions",
- fieldtype: "Table",
- in_place_edit: 1,
- label: __("Questions"),
- fields: [
- {
- fieldname: "question",
- fieldtype: "Link",
- label: __("Question"),
- options: "LMS Question",
- in_list_view: 1,
- only_select: 1,
- reqd: 1,
- },
- {
- fieldname: "marks",
- fieldtype: "Int",
- label: __("Marks"),
- in_list_view: 1,
- reqd: 1,
- },
- {
- fieldname: "question_name",
- fieldname: "Link",
- options: "LMS Quiz Question",
- label: __("Question Name"),
- },
- ],
- },
- ],
- body: $(".questions-table").get(0),
- });
- this.table.make();
- $(".questions-table .form-section:last").removeClass("empty-section");
- $(".questions-table .frappe-control").removeClass("hide-control");
- $(".questions-table .form-column").addClass("p-0");
-
- quiz_questions.forEach((question, idx) => {
- add_question_row(question, idx);
- });
- this.table.fields_dict["questions"].grid.add_custom_button(
- "New Question",
- show_question_modal,
- "bottom"
- );
-};
-
-const add_question_row = (question, idx) => {
- this.table.fields_dict["questions"].grid.add_new_row();
- this.table.get_value("questions")[idx] = {
- question: question.question,
- marks: question.marks,
- };
- this.table.refresh();
-};
-
-const fetch_question_data = (e) => {
- let question_name = $(e.currentTarget)
- .find(".btn-open")
- .attr("href")
- .split("/")[3];
-
- frappe.call({
- method: "lms.lms.doctype.lms_question.lms_question.get_question_details",
- args: {
- question: question_name,
- },
- callback: (data) => {
- show_question_modal(data.message);
- },
- });
-};
diff --git a/lms/www/batch/quiz.py b/lms/www/batch/quiz.py
deleted file mode 100644
index 2df008b7..00000000
--- a/lms/www/batch/quiz.py
+++ /dev/null
@@ -1,39 +0,0 @@
-import frappe
-from frappe.utils import cstr
-from frappe import _
-from lms.lms.utils import has_course_instructor_role, has_course_moderator_role
-
-
-def get_context(context):
- context.no_cache = 1
-
- if not has_course_moderator_role() or not has_course_instructor_role():
- 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))
-
- quizname = frappe.form_dict["quizname"]
- if quizname == "new-quiz":
- context.quiz = frappe._dict()
- else:
-
- context.quiz = frappe.db.get_value(
- "LMS Quiz",
- quizname,
- [
- "title",
- "name",
- "max_attempts",
- "passing_percentage",
- "show_answers",
- "show_submission_history",
- ],
- as_dict=1,
- )
-
- fields_arr = ["name", "question", "marks"]
- context.quiz.questions = frappe.get_all(
- "LMS Quiz Question", {"parent": quizname}, fields_arr, order_by="idx"
- )
diff --git a/lms/www/batch/quiz_list.html b/lms/www/batch/quiz_list.html
deleted file mode 100644
index c53881bd..00000000
--- a/lms/www/batch/quiz_list.html
+++ /dev/null
@@ -1,65 +0,0 @@
-{% extends "templates/base.html" %}
-{% block title %}
- {{ _("Quiz List") }}
-{% endblock %}
-
-
-{% block content %}
-
-
- {{ Header() }}
- {% if quiz_list | length %}
- {{ QuizList(quiz_list) }}
- {% else %}
- {{ EmptyState() }}
- {% endif %}
-
-
-{% endblock %}
-
-{% macro Header() %}
-
-{% endmacro %}
-
-{% macro QuizList(quiz_list) %}
-
-{% endmacro %}
-
-{% macro EmptyState() %}
-
-
-
-
- {{ _("You have not created any quiz yet.") }}
-
-
- {{ _("Create a quiz and add it to your course to engage your users.") }}
-
-
-
-{% endmacro %}
diff --git a/lms/www/batch/quiz_list.py b/lms/www/batch/quiz_list.py
deleted file mode 100644
index ee4321a7..00000000
--- a/lms/www/batch/quiz_list.py
+++ /dev/null
@@ -1,17 +0,0 @@
-import frappe
-from lms.lms.utils import has_course_instructor_role, has_course_moderator_role
-from frappe import _
-
-
-def get_context(context):
- context.no_cache = 1
-
- if not has_course_moderator_role() or not has_course_instructor_role():
- 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))
-
- filters = {} if has_course_moderator_role() else {"owner": frappe.session.user}
- context.quiz_list = frappe.get_all("LMS Quiz", filters, ["name", "title"])
diff --git a/lms/www/batches/__init__.py b/lms/www/batches/__init__.py
deleted file mode 100644
index e69de29b..00000000
diff --git a/lms/www/batches/batch.html b/lms/www/batches/batch.html
deleted file mode 100644
index f368c70c..00000000
--- a/lms/www/batches/batch.html
+++ /dev/null
@@ -1,652 +0,0 @@
-{% extends "lms/templates/lms_base.html" %}
-{% block title %}
- {{ _(batch_info.title) }}
-{% endblock %}
-
-
-{% block page_content %}
-
-
- {{ BreadCrumb(batch_info) }}
-
- {{ BatchDetails(batch_info) }}
- {{ BatchSections(batch_info, batch_courses, batch_students, flow) }}
-
-
-
-{% endblock %}
-
-
-
-{% macro BreadCrumb(batch_info) %}
-
-{% endmacro %}
-
-
-
-{% macro BatchDetails(batch_info) %}
-
-
-
- {{ batch_info.title }}
-
-
- {% if batch_info.description %}
-
- {{ batch_info.description }}
-
- {% endif %}
-
-
-
-
-
-
-
- {{ frappe.utils.format_date(batch_info.start_date, "long") }}
-
-
- {% if batch_info.start_date != batch_info.end_date %}
-
- - {{ frappe.utils.format_date(batch_info.end_date, "long") }}
-
- {% endif %}
-
-
-
-
-
-
-
-
- {{ batch_courses | length }} {{ _("Courses") }}
-
-
-
-
-
-
-
-
- {{ batch_students | length }} {{ _("Students") }}
-
-
-
- {% if batch_info.custom_component %}
-
- {{ batch_info.custom_component }}
-
- {% endif %}
-
-{% endmacro %}
-
-
-{% macro BatchSections(batch_info, batch_courses, batch_students, flow) %}
-
-
-
-
-
-
-
-
- {% if settings.show_dashboard and is_student %}
-
- {{ Dashboard(batch_info, batch_courses, current_student) }}
-
- {% endif %}
-
- {% if settings.show_courses %}
-
- {{ CoursesSection(batch_info, batch_courses) }}
-
- {% endif %}
-
- {% if show_timetable %}
-
- {{ Timetable() }}
-
- {% endif %}
-
- {% if is_moderator %}
- {% if settings.show_students %}
-
- {{ StudentsSection(batch_info, batch_students) }}
-
- {% endif %}
-
- {% if settings.show_assessments %}
-
- {{ AssessmentsSection(batch_info) }}
-
- {% endif %}
-
- {% if settings.show_emails %}
-
- {{ EmailsSection() }}
-
- {% endif %}
- {% endif %}
-
- {% if batch_students | length and (is_moderator or is_student or is_evaluator) %}
- {% if settings.show_discussions %}
-
- {{ Discussions(batch_info) }}
-
- {% endif %}
-
- {% if settings.show_live_class %}
-
- {{ LiveClassSection(batch_info, live_classes) }}
-
- {% endif %}
- {% endif %}
-
- {% if custom_tabs_content %}
- {% include custom_tabs_content %}
- {% endif %}
-
-
-
-{% endmacro %}
-
-{% macro Dashboard(batch_info, batch_courses, current_student) %}
-
-{% set upcoming_evals = current_student.upcoming_evals %}
-{% set assessments = current_student.assessments %}
-{% set student = current_student %}
-
-
- {% if student.name == frappe.session.user %}
-
- {{ _("Schedule Evaluation") }}
-
- {% endif %}
-
-
- {% include "lms/templates/upcoming_evals.html" %}
-
-
- {% include "lms/templates/assessments.html" %}
-
-
-{% endmacro %}
-
-{% macro Discussions(batch_info) %}
-
- {% set condition = is_moderator or is_student or is_evaluator %}
- {% set doctype, docname = _("LMS Batch"), batch_info.name %}
- {% set single_thread = True %}
- {% set title = "Discussions" %}
- {% set cta_title = "Post" %}
- {% set button_name = _("Start Learning") %}
- {% set redirect_to = "/batches/" + batch_info.name %}
- {% set empty_state_title = _("Have a doubt?") %}
- {% set empty_state_subtitle = _("Post it here, our mentors will help you out.") %}
- {% include "frappe/templates/discussions/discussions_section.html" %}
-
-{% endmacro %}
-
-{% macro CoursesSection(batch_info, batch_courses) %}
-
-
-
- {% if batch_courses | length %}
-
- {% for course in batch_courses %}
-
- {{ widgets.CourseCard(course=course, read_only=False) }}
-
-
- {% endfor %}
-
- {% else %}
-
- {{ _("No courses") }}
-
- {% endif %}
-
-
-{% endmacro %}
-
-
-{% macro StudentsSection(batch_info, batch_students) %}
-
-
-
- {% if batch_students | length %}
-
- {% else %}
- {{ _("No Students") }}
- {% endif %}
-
-{% endmacro %}
-
-
-{% macro AssessmentsSection(batch_info) %}
-
-
- {{ AssessmentList(assessments) }}
-
-{% endmacro %}
-
-
-{% macro EmailsSection() %}
-
-
- {{ _("Email to Students") }}
-
-
-
- {% for email in batch_emails %}
-
-
-
-
- {% set member = frappe.db.get_value("User", email.sender, ["full_name", "username", "name", "user_image"], as_dict=1) %}
- {{ widgets.Avatar(member=member, avatar_class="avatar-small") }}
-
-
- {{ member.full_name }}
-
-
- {{ frappe.utils.pretty_date(email.communication_date) }}
-
-
-
-
-
-
- {{ email.content }}
-
-
- {% endfor %}
-
-{% endmacro %}
-
-
-{% macro AssessmentList(assessments) %}
-{% if assessments | length %}
-
- {% else %}
-
{{ _("No Assessments") }}
- {% endif %}
-{% endmacro %}
-
-
-{% macro LiveClassSection(batch_info, live_classes) %}
-
-
- {{ CreateLiveClass(batch_info) }}
- {{ LiveClassList(batch_info, live_classes) }}
-
-{% endmacro %}
-
-
-{% macro CreateLiveClass(batch_info) %}
-{% if is_moderator %}
-
-{% endif %}
-{% endmacro %}
-
-
-{% macro LiveClassList(batch_info, live_classes) %}
-
- {% if live_classes | length %}
- {% for class in live_classes %}
-
-
-
-
-
-
-
-
- {{ class.title }}
-
-
-
-
-
-
- {{ frappe.utils.format_date(class.date, "full") }}
-
-
-
-
-
- {{ frappe.utils.format_time(class.time, "hh:mm a") }}
-
-
-
- {{ class.description }}
-
-
-
- {% endfor %}
- {% else %}
-
{{ _("No Live Classes") }}
- {% endif %}
-
-{% endmacro %}
-
-
-{% macro Timetable() %}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {% for legend in legends %}
-
- {% endfor %}
-
-
-
-
-
-{% endmacro %}
-
-{%- block script %}
- {{ super() }}
- {% if batch_info.custom_script %}
-
- {% endif %}
-
-
-
-
-
-{% endblock %}
diff --git a/lms/www/batches/batch.js b/lms/www/batches/batch.js
deleted file mode 100644
index 6e27ca10..00000000
--- a/lms/www/batches/batch.js
+++ /dev/null
@@ -1,931 +0,0 @@
-frappe.ready(() => {
- let self = this;
- frappe.require("controls.bundle.js");
-
- if ($("#calendar").length) {
- setup_timetable();
- }
-
- if ($("#calendar").length) {
- $(document).on("click", "#prev-week", (e) => {
- this.calendar_ && this.calendar_.prev();
- set_calendar_range(this.calendar_, this.events);
- });
- }
-
- if ($("#calendar").length) {
- $(document).on("click", "#next-week", (e) => {
- this.calendar_ && this.calendar_.next();
- set_calendar_range(this.calendar_, this.events);
- });
- }
-
- if ($("#live-class-form").length) {
- setTimeout(() => {
- make_live_class_form();
- }, 1000);
- }
-
- $(".btn-add-student").click((e) => {
- show_student_modal(e);
- });
-
- $(".btn-remove-student").click((e) => {
- remove_student(e);
- });
-
- $("#open-class-modal").click((e) => {
- e.preventDefault();
- $("#live-class-modal").modal("show");
- });
-
- $("#create-live-class").click((e) => {
- create_live_class(e);
- });
-
- $(".btn-remove-assessment").click((e) => {
- remove_assessment(e);
- });
-
- $("#open-assessment-modal").click((e) => {
- e.preventDefault();
- show_assessment_modal();
- });
-
- $(".btn-close").click((e) => {
- window.location.reload();
- });
-
- $(".btn-schedule-eval").click((e) => {
- open_evaluation_form(e);
- });
-
- $(document).on("click", ".slot", (e) => {
- mark_active_slot(e);
- });
-
- $(".btn-email").click((e) => {
- email_to_students();
- });
-});
-
-const create_live_class = (e) => {
- let batch_name = $(".class-details").data("batch");
- frappe.call({
- method: "lms.lms.doctype.lms_batch.lms_batch.create_live_class",
- args: {
- batch_name: batch_name,
- title: $("input[data-fieldname='meeting_title']").val(),
- duration: $("input[data-fieldname='meeting_duration']").val(),
- date: $("input[data-fieldname='meeting_date']").val(),
- time: $("input[data-fieldname='meeting_time']").val(),
- timezone: $('select[data-fieldname="meeting_timezone"]').val(),
- auto_recording: $(
- 'select[data-fieldname="meeting_recording"]'
- ).val(),
- description: $(
- "textarea[data-fieldname='meeting_description']"
- ).val(),
- },
- callback: (data) => {
- $("#live-class-modal").modal("hide");
- frappe.show_alert(
- {
- message: __("Live Class added successfully"),
- indicator: "green",
- },
- 3
- );
- setTimeout(function () {
- window.location.reload();
- }, 1000);
- },
- });
-};
-
-const make_live_class_form = (e) => {
- this.field_group = new frappe.ui.FieldGroup({
- fields: [
- {
- fieldname: "meeting_title",
- fieldtype: "Data",
- options: "",
- label: "Title",
- reqd: 1,
- },
- {
- fieldname: "meeting_time",
- fieldtype: "Time",
- options: "",
- label: "Time",
- reqd: 1,
- },
- {
- fieldname: "meeting_timezone",
- label: __("Time Zone"),
- fieldtype: "Select",
- options: get_timezones().join("\n"),
- reqd: 1,
- },
- {
- fieldname: "meeting_col",
- fieldtype: "Column Break",
- options: "",
- },
- {
- fieldname: "meeting_date",
- fieldtype: "Date",
- options: "",
- label: "Date",
- reqd: 1,
- },
- {
- fieldname: "meeting_duration",
- fieldtype: "Int",
- options: "",
- label: "Duration (in Minutes)",
- reqd: 1,
- },
- {
- fieldname: "meeting_recording",
- fieldtype: "Select",
- options: "No Recording\nLocal\nCloud",
- label: "Auto Recording",
- default: "No Recording",
- },
- {
- fieldname: "meeting_sec",
- fieldtype: "Section Break",
- options: "",
- },
- {
- fieldname: "meeting_description",
- fieldtype: "Small Text",
- options: "",
- max_height: 100,
- min_lines: 5,
- label: "Description",
- },
- ],
- body: $("#live-class-form").get(0),
- });
-
- this.field_group.make();
- $("#live-class-form .form-section:last").removeClass("empty-section");
- $("#live-class-form .frappe-control").removeClass("hide-control");
-};
-
-const get_timezones = () => {
- return [
- "Pacific/Midway",
- "Pacific/Pago_Pago",
- "Pacific/Honolulu",
- "America/Anchorage",
- "America/Vancouver",
- "America/Los_Angeles",
- "America/Tijuana",
- "America/Edmonton",
- "America/Denver",
- "America/Phoenix",
- "America/Mazatlan",
- "America/Winnipeg",
- "America/Regina",
- "America/Chicago",
- "America/Mexico_City",
- "America/Guatemala",
- "America/El_Salvador",
- "America/Managua",
- "America/Costa_Rica",
- "America/Montreal",
- "America/New_York",
- "America/Indianapolis",
- "America/Panama",
- "America/Bogota",
- "America/Lima",
- "America/Halifax",
- "America/Puerto_Rico",
- "America/Caracas",
- "America/Santiago",
- "America/St_Johns",
- "America/Montevideo",
- "America/Araguaina",
- "America/Argentina/Buenos_Aires",
- "America/Godthab",
- "America/Sao_Paulo",
- "Atlantic/Azores",
- "Canada/Atlantic",
- "Atlantic/Cape_Verde",
- "UTC",
- "Etc/Greenwich",
- "Europe/Belgrade",
- "CET",
- "Atlantic/Reykjavik",
- "Europe/Dublin",
- "Europe/London",
- "Europe/Lisbon",
- "Africa/Casablanca",
- "Africa/Nouakchott",
- "Europe/Oslo",
- "Europe/Copenhagen",
- "Europe/Brussels",
- "Europe/Berlin",
- "Europe/Helsinki",
- "Europe/Amsterdam",
- "Europe/Rome",
- "Europe/Stockholm",
- "Europe/Vienna",
- "Europe/Luxembourg",
- "Europe/Paris",
- "Europe/Zurich",
- "Europe/Madrid",
- "Africa/Bangui",
- "Africa/Algiers",
- "Africa/Tunis",
- "Africa/Harare",
- "Africa/Nairobi",
- "Europe/Warsaw",
- "Europe/Prague",
- "Europe/Budapest",
- "Europe/Sofia",
- "Europe/Istanbul",
- "Europe/Athens",
- "Europe/Bucharest",
- "Asia/Nicosia",
- "Asia/Beirut",
- "Asia/Damascus",
- "Asia/Jerusalem",
- "Asia/Amman",
- "Africa/Tripoli",
- "Africa/Cairo",
- "Africa/Johannesburg",
- "Europe/Moscow",
- "Asia/Baghdad",
- "Asia/Kuwait",
- "Asia/Riyadh",
- "Asia/Bahrain",
- "Asia/Qatar",
- "Asia/Aden",
- "Asia/Tehran",
- "Africa/Khartoum",
- "Africa/Djibouti",
- "Africa/Mogadishu",
- "Asia/Dubai",
- "Asia/Muscat",
- "Asia/Baku",
- "Asia/Kabul",
- "Asia/Yekaterinburg",
- "Asia/Tashkent",
- "Asia/Calcutta",
- "Asia/Kathmandu",
- "Asia/Novosibirsk",
- "Asia/Almaty",
- "Asia/Dacca",
- "Asia/Krasnoyarsk",
- "Asia/Dhaka",
- "Asia/Bangkok",
- "Asia/Saigon",
- "Asia/Jakarta",
- "Asia/Irkutsk",
- "Asia/Shanghai",
- "Asia/Hong_Kong",
- "Asia/Taipei",
- "Asia/Kuala_Lumpur",
- "Asia/Singapore",
- "Australia/Perth",
- "Asia/Yakutsk",
- "Asia/Seoul",
- "Asia/Tokyo",
- "Australia/Darwin",
- "Australia/Adelaide",
- "Asia/Vladivostok",
- "Pacific/Port_Moresby",
- "Australia/Brisbane",
- "Australia/Sydney",
- "Australia/Hobart",
- "Asia/Magadan",
- "SST",
- "Pacific/Noumea",
- "Asia/Kamchatka",
- "Pacific/Fiji",
- "Pacific/Auckland",
- "Asia/Kolkata",
- "Europe/Kiev",
- "America/Tegucigalpa",
- "Pacific/Apia",
- ];
-};
-
-const show_student_modal = () => {
- let student_modal = new frappe.ui.Dialog({
- title: "Add Student",
- fields: [
- {
- fieldtype: "Link",
- options: "User",
- label: __("Student"),
- fieldname: "student",
- reqd: 1,
- only_select: 1,
- filters: {
- ignore_user_type: 1,
- },
- filter_description: " ",
- },
- ],
- primary_action_label: __("Add"),
- primary_action(values) {
- add_student(values);
- student_modal.hide();
- },
- });
- student_modal.show();
- setTimeout(() => {
- $(".modal-body").css("min-height", "200px");
- }, 1000);
-};
-
-const add_student = (values) => {
- frappe.call({
- method: "frappe.client.insert",
- args: {
- doc: {
- doctype: "Batch Student",
- student: values.student,
- parenttype: "LMS Batch",
- parentfield: "students",
- parent: $(".class-details").data("batch"),
- },
- },
- callback(r) {
- frappe.show_alert(
- {
- message: __("Student Added"),
- indicator: "green",
- },
- 2000
- );
- window.location.reload();
- },
- });
-};
-
-const remove_student = (e) => {
- frappe.confirm(
- "Are you sure you want to remove this student from the batch?",
- () => {
- frappe.call({
- method: "lms.lms.doctype.lms_batch.lms_batch.remove_student",
- args: {
- student: $(e.currentTarget).data("student"),
- batch_name: $(".class-details").data("batch"),
- },
- callback: (data) => {
- frappe.show_alert(
- {
- message: __("Student removed successfully"),
- indicator: "green",
- },
- 2000
- );
- window.location.reload();
- },
- });
- }
- );
-};
-
-const show_assessment_modal = (e) => {
- let assessment_modal = new frappe.ui.Dialog({
- title: "Manage Assessments",
- fields: [
- {
- fieldtype: "Link",
- options: "DocType",
- label: __("Assessment Type"),
- fieldname: "assessment_type",
- reqd: 1,
- only_select: 1,
- filters: {
- name: ["in", ["LMS Assignment", "LMS Quiz"]],
- },
- filter_description: " ",
- },
- {
- fieldtype: "Dynamic Link",
- options: "assessment_type",
- label: __("Assessment"),
- fieldname: "assessment_name",
- reqd: 1,
- only_select: 1,
- },
- {
- fieldtype: "Section Break",
- label: __("OR"),
- },
- {
- fieldtype: "Button",
- label: __("Create Assignment"),
- fieldname: "create_assignment",
- click: () => {
- window.location.href = "/assignments";
- },
- },
- {
- fieldtype: "Column Break",
- },
- {
- fieldtype: "Button",
- label: __("Create Quiz"),
- fieldname: "create_quiz",
- click: () => {
- window.location.href = "/quizzes";
- },
- },
- ],
- primary_action_label: __("Add"),
- primary_action(values) {
- add_addessment(values);
- assessment_modal.hide();
- },
- });
- assessment_modal.show();
- setTimeout(() => {
- $(".modal-body").css("min-height", "300px");
- }, 1000);
-};
-
-const add_addessment = (values) => {
- frappe.call({
- method: "frappe.client.insert",
- args: {
- doc: {
- doctype: "LMS Assessment",
- assessment_type: values.assessment_type,
- assessment_name: values.assessment_name,
- parenttype: "LMS Batch",
- parentfield: "assessment",
- parent: $(".class-details").data("batch"),
- },
- },
- callback(r) {
- frappe.show_alert(
- {
- message: __("Assessment Added"),
- indicator: "green",
- },
- 2000
- );
- window.location.reload();
- },
- });
-};
-
-const remove_assessment = (e) => {
- frappe.confirm("Are you sure you want to remove this assessment?", () => {
- frappe.call({
- method: "lms.lms.doctype.lms_batch.lms_batch.remove_assessment",
- args: {
- assessment: $(e.currentTarget).data("assessment"),
- parent: $(".class-details").data("batch"),
- },
- callback(r) {
- frappe.show_alert(
- {
- message: __("Assessment Removed"),
- indicator: "green",
- },
- 2000
- );
- window.location.reload();
- },
- });
- });
-};
-
-const open_evaluation_form = (e) => {
- this.eval_form = new frappe.ui.Dialog({
- title: __("Schedule Evaluation"),
- fields: [
- {
- fieldtype: "Link",
- fieldname: "course",
- label: __("Course"),
- options: "LMS Course",
- reqd: 1,
- filters: {
- name: ["in", courses],
- },
- filter_description: " ",
- only_select: 1,
- change: () => {
- this.eval_form.set_value("date", "");
- $("[data-fieldname='slots']").html("");
- },
- },
- {
- fieldtype: "Date",
- fieldname: "date",
- label: __("Date"),
- reqd: 1,
- min_date: new Date(
- frappe.datetime.add_days(frappe.datetime.get_today(), 1)
- ),
- max_date: evaluation_end_date
- ? new Date(evaluation_end_date)
- : "",
- change: () => {
- if (this.eval_form.get_value("date")) get_slots();
- },
- },
- {
- fieldtype: "HTML",
- fieldname: "slots",
- label: __("Slots"),
- },
- ],
- primary_action: (values) => {
- submit_evaluation_form(values);
- },
- });
- this.eval_form.show();
- setTimeout(() => {
- $(".modal-body").css("min-height", "300px");
- }, 1000);
-};
-
-const get_slots = () => {
- frappe.call({
- method: "lms.lms.doctype.course_evaluator.course_evaluator.get_schedule",
- args: {
- course: this.eval_form.get_value("course"),
- date: this.eval_form.get_value("date"),
- batch: $(".class-details").data("batch"),
- },
- callback: (r) => {
- if (r.message) {
- display_slots(r.message);
- }
- },
- });
-};
-
-const display_slots = (slots) => {
- let slot_html = "";
- let slots_available = false;
- if (slots.length) {
- slot_html = `
-
${__("Select a Slot")}
-
`;
- let day = moment(this.eval_form.get_value("date")).format("dddd");
-
- slots.forEach((slot) => {
- if (slot.day == day) {
- slots_available = true;
- slot_html += `
- ${moment(slot.start_time, "hh:mm").format("hh:mm a")} -
- ${moment(slot.end_time, "hh:mm").format("hh:mm a")}
-
`;
- }
- });
- slot_html += "
";
- }
-
- if (!slots_available) {
- slot_html = `
- No slots available for this date.
-
`;
- }
-
- $("[data-fieldname='slots']").html(slot_html);
-};
-
-const mark_active_slot = (e) => {
- $(".slot").removeClass("btn-outline-primary");
- $(e.currentTarget).addClass("btn-outline-primary");
- this.current_slot = $(e.currentTarget);
-};
-
-const submit_evaluation_form = (values) => {
- if (!this.current_slot) {
- frappe.throw(__("Please select a slot"));
- }
-
- frappe.call({
- method: "lms.lms.doctype.lms_certificate_request.lms_certificate_request.create_certificate_request",
- args: {
- course: values.course,
- date: values.date,
- start_time: this.current_slot.data("start"),
- end_time: this.current_slot.data("end"),
- day: this.current_slot.data("day"),
- batch_name: $(".class-details").data("batch"),
- },
- callback: (r) => {
- this.eval_form.hide();
- frappe.show_alert({
- message: __("Evaluation scheduled successfully"),
- indicator: "green",
- });
- setTimeout(() => {
- window.location.reload();
- }, 1000);
- },
- });
-};
-
-const setup_timetable = () => {
- let self = this;
- frappe.call({
- method: "lms.lms.doctype.lms_batch.lms_batch.get_batch_timetable",
- args: {
- batch: $(".class-details").data("batch"),
- },
- callback: (r) => {
- if (r.message.length) {
- setup_calendar(r.message);
- self.events = r.message;
- }
- },
- });
-};
-
-const setup_calendar = (events) => {
- const element = $("#calendar");
- const Calendar = tui.Calendar;
- const calendar_id = "calendar1";
- const container = element[0];
- const options = get_calendar_options(element, calendar_id);
- const calendar = new Calendar(container, options);
- this.calendar_ = calendar;
-
- create_events(calendar, events, calendar_id);
- add_links_to_events(calendar, events);
- scroll_to_date(calendar, events);
- set_calendar_range(calendar, events);
-};
-
-const get_calendar_options = (element, calendar_id) => {
- const start_time = element.data("start");
- const end_time = element.data("end");
-
- return {
- defaultView: $(window).width() < 768 || show_day_view ? "day" : "week",
- usageStatistics: false,
- week: {
- narrowWeekend: true,
- hourStart: parseInt(start_time.split(":")[0]) - 1,
- /* hourEnd: parseInt(end_time.split(":")[0]) + 1, */
- },
- month: {
- narrowWeekend: true,
- },
- taskView: false,
- isReadOnly: true,
- calendars: [
- {
- id: calendar_id,
- name: "Timetable",
- backgroundColor: "var(--fg-color)",
- },
- ],
- template: {
- allday: function (event) {
- let hide = event.raw.completed ? "" : "hide";
- return `
-
-
${event.title}
-
`;
- },
- time: function (event) {
- let hide = event.raw.completed ? "" : "hide";
- return `
-
-
- ${event.title}
-
- ${frappe.datetime.get_time(event.start.d.d)} - ${frappe.datetime.get_time(
- event.end.d.d
- )}
-
-
-
`;
- },
- },
- };
-};
-
-const create_events = (calendar, events, calendar_id) => {
- let calendar_events = [];
- events.forEach((event, idx) => {
- let clr = get_background_color(event.reference_doctype);
- calendar_events.push({
- id: `event${idx}`,
- calendarId: calendar_id,
- title: event.title,
- start: `${event.date}T${format_time(event.start_time)}`,
- end: `${event.date}T${format_time(event.end_time)}`,
- isAllday: event.start_time ? false : true,
- category: event.start_time ? "time" : "allday",
- borderColor: clr,
- backgroundColor: "var(--fg-color)",
- customStyle: {
- borderRadius: "var(--border-radius-md)",
- boxShadow: "var(--shadow-base)",
- borderWidth: "8px",
- padding: "0.25rem 0.5rem 0.5rem",
- },
- raw: {
- url: event.url,
- milestone: event.milestone,
- name: event.name,
- idx: event.idx,
- parent: event.parent,
- completed: event.completed,
- },
- });
- });
-
- calendar.createEvents(calendar_events);
-};
-
-const format_time = (time) => {
- if (!time) return "00:00:00";
- let time_arr = time.split(":");
- if (time_arr[0] < 10) time_arr[0] = "0" + time_arr[0];
- return time_arr.join(":");
-};
-
-const add_links_to_events = (calendar) => {
- calendar.on("clickEvent", ({ event }) => {
- let event_date = event.start.d.d;
- event_date = moment(event_date).format("YYYY-MM-DD");
- let current_date = moment().format("YYYY-MM-DD");
-
- if (
- is_student &&
- !moment(event_date).isSameOrBefore(current_date) &&
- !allow_future
- )
- return;
-
- if (is_student && event.raw.milestone) {
- frappe.call({
- method: "lms.lms.doctype.lms_batch.lms_batch.is_milestone_complete",
- args: {
- idx: event.raw.idx,
- batch: event.raw.parent,
- },
- callback: (data) => {
- if (data.message) window.open(event.raw.url, "_blank");
- else
- frappe.show_alert({
- message:
- "Please complete all previous activities to proceed.",
- indicator: "red",
- });
- },
- });
- } else window.open(event.raw.url, "_blank");
- });
-};
-
-const scroll_to_date = (calendar, events) => {
- if (
- new Date() < new Date(events[0].date) ||
- new Date() > new Date(events.slice(-1)[0].date)
- ) {
- calendar.setDate(new Date(events[0].date));
- }
-};
-
-const set_calendar_range = (calendar, events) => {
- let day_view = $(window).width() < 768 || show_day_view ? true : false;
- if (day_view) {
- let calendar_date = moment(calendar.getDate().d.d).format(
- "DD MMMM YYYY"
- );
- $(".calendar-range").text(`${calendar_date}`);
-
- if (moment(calendar_date).isSameOrBefore(moment(events[0].date)))
- $("#prev-week").hide();
- else $("#prev-week").show();
-
- if (
- moment(calendar_date).isSameOrAfter(
- moment(events.slice(-1)[0].date)
- )
- )
- $("#next-week").hide();
- else $("#next-week").show();
- } else {
- let week_start = moment(calendar.getDateRangeStart().d.d);
- let week_end = moment(calendar.getDateRangeEnd().d.d);
-
- $(".calendar-range").text(
- `${moment(week_start).format("DD MMMM YYYY")} - ${moment(
- week_end
- ).format("DD MMMM YYYY")}`
- );
-
- if (week_start.diff(moment(events[0].date), "days") <= 0)
- $("#prev-week").hide();
- else $("#prev-week").show();
-
- if (week_end.diff(moment(events.slice(-1)[0].date), "days") > 0)
- $("#next-week").hide();
- else $("#next-week").show();
- }
-};
-
-const get_background_color = (doctype) => {
- const match = legends.filter((legend) => {
- return legend.reference_doctype == doctype;
- });
- if (match.length) return match[0].color;
-};
-
-const email_to_students = () => {
- this.email_dialog = new frappe.ui.Dialog({
- title: __("Email to Students"),
- fields: [
- {
- fieldtype: "Data",
- fieldname: "subject",
- label: __("Subject"),
- reqd: 1,
- },
- {
- fieldtype: "Data",
- fieldname: "reply_to",
- label: __("Reply To"),
- reqd: 0,
- },
- {
- fieldtype: "Text Editor",
- fieldname: "message",
- label: __("Message"),
- reqd: 1,
- max_height: 100,
- min_lines: 5,
- },
- ],
- primary_action: (values) => {
- send_email(values);
- },
- });
- this.email_dialog.show();
-};
-
-const send_email = (values) => {
- frappe.call({
- method: "frappe.client.get_list",
- args: {
- doctype: "Batch Student",
- parent: "LMS Batch",
- fields: ["student"],
- filters: {
- parent: $(".class-details").data("batch"),
- },
- },
- callback: (data) => {
- send_email_to_students(data.message, values);
- },
- });
-};
-
-const send_email_to_students = (students, values) => {
- students = students.map((row) => row.student);
- frappe.call({
- method: "frappe.core.doctype.communication.email.make",
- args: {
- recipients: students.join(", "),
- cc: values.reply_to,
- subject: values.subject,
- content: values.message,
- doctype: "LMS Batch",
- name: $(".class-details").data("batch"),
- send_email: 1,
- },
- callback: (r) => {
- this.email_dialog.hide();
- frappe.show_alert({
- message: __("Email sent successfully"),
- indicator: "green",
- });
- setTimeout(() => {
- window.location.reload();
- }, 2000);
- },
- });
-};
diff --git a/lms/www/batches/batch.py b/lms/www/batches/batch.py
deleted file mode 100644
index c03e9e9f..00000000
--- a/lms/www/batches/batch.py
+++ /dev/null
@@ -1,278 +0,0 @@
-from frappe import _
-import frappe
-from frappe.utils import getdate
-from lms.www.utils import get_assessments, is_student
-from lms.lms.utils import (
- has_course_moderator_role,
- has_course_evaluator_role,
- get_upcoming_evals,
- has_submitted_assessment,
- has_graded_assessment,
- get_lesson_index,
- get_lesson_url,
- get_lesson_icon,
- get_membership,
-)
-
-
-def get_context(context):
- context.no_cache = 1
- batch_name = frappe.form_dict["batchname"]
- context.is_moderator = has_course_moderator_role()
- context.is_evaluator = has_course_evaluator_role()
-
- context.batch_info = frappe.db.get_value(
- "LMS Batch",
- batch_name,
- [
- "name",
- "title",
- "start_date",
- "end_date",
- "description",
- "medium",
- "custom_component",
- "custom_script",
- "seat_count",
- "start_time",
- "end_time",
- "category",
- "paid_batch",
- "amount",
- "currency",
- "batch_details",
- "published",
- "allow_future",
- "evaluation_end_date",
- "meta_image",
- ],
- as_dict=True,
- )
-
- context.reference_doctype = "LMS Batch"
- context.reference_name = batch_name
-
- batch_courses = frappe.get_all(
- "Batch Course",
- {"parent": batch_name},
- ["name", "course", "title"],
- order_by="idx",
- )
-
- batch_students = frappe.get_all(
- "Batch Student",
- {"parent": batch_name},
- ["name", "student", "student_name", "username"],
- order_by="idx",
- )
-
- context.batch_courses = get_class_course_details(batch_courses)
- context.course_list = [course.course for course in context.batch_courses]
- context.all_courses = frappe.get_all(
- "LMS Course", fields=["name", "title"], limit_page_length=0
- )
- context.course_name_list = [course.course for course in context.batch_courses]
- context.assessments = get_assessments(batch_name)
- context.batch_emails = frappe.get_all(
- "Communication",
- filters={"reference_doctype": "LMS Batch", "reference_name": batch_name},
- fields=["subject", "content", "recipients", "cc", "communication_date", "sender"],
- order_by="communication_date desc",
- )
-
- context.batch_students = get_class_student_details(
- batch_students, batch_courses, context.assessments
- )
- context.is_student = is_student(batch_name)
-
- if not context.is_student and not context.is_moderator and not context.is_evaluator:
- raise frappe.PermissionError(_("You don't have permission to access this page."))
-
- context.live_classes = frappe.get_all(
- "LMS Live Class",
- {"batch_name": batch_name, "date": [">=", getdate()]},
- ["title", "description", "time", "date", "start_url", "join_url", "owner"],
- order_by="date",
- )
-
- context.current_student = (
- get_current_student_details(batch_courses, batch_name) if context.is_student else None
- )
- context.all_assignments = get_all_assignments(batch_name)
- context.all_quizzes = get_all_quizzes(batch_name)
- context.show_timetable = frappe.db.count(
- "LMS Batch Timetable",
- {
- "parent": batch_name,
- },
- )
- context.legends = get_legends(batch_name)
- context.settings = frappe.get_single("LMS Settings")
-
- custom_tabs = frappe.get_hooks("lms_batch_tabs")
- if custom_tabs:
- context.custom_tabs_header = custom_tabs.get("header_html")[0]
- context.custom_tabs_content = custom_tabs.get("content_html")[0]
- context.update(frappe.get_attr(custom_tabs.get("context")[0])())
-
-
-def get_all_quizzes(batch_name):
- filters = {} if has_course_moderator_role() else {"owner": frappe.session.user}
- all_quizzes = frappe.get_all("LMS Quiz", filters, ["name", "title"])
- for quiz in all_quizzes:
- quiz.checked = frappe.db.exists(
- {
- "doctype": "LMS Assessment",
- "assessment_type": "LMS Quiz",
- "assessment_name": quiz.name,
- "parent": batch_name,
- }
- )
- return all_quizzes
-
-
-def get_all_assignments(batch_name):
- filters = {} if has_course_moderator_role() else {"owner": frappe.session.user}
- all_assignments = frappe.get_all("LMS Assignment", filters, ["name", "title"])
- for assignment in all_assignments:
- assignment.checked = frappe.db.exists(
- {
- "doctype": "LMS Assessment",
- "assessment_type": "LMS Assignment",
- "assessment_name": assignment.name,
- "parent": batch_name,
- }
- )
- return all_assignments
-
-
-def get_class_course_details(batch_courses):
- for course in batch_courses:
- details = frappe.db.get_value(
- "LMS Course",
- course.course,
- [
- "name",
- "title",
- "image",
- "upcoming",
- "short_introduction",
- "paid_course",
- "course_price",
- "enable_certification",
- "currency",
- ],
- as_dict=True,
- )
- course.update(details)
- return batch_courses
-
-
-def get_class_student_details(batch_students, batch_courses, assessments):
- for student in batch_students:
- student.update(
- frappe.db.get_value(
- "User", student.student, ["name", "full_name", "username", "headline"], as_dict=1
- )
- )
- student.update(frappe.db.get_value("User", student.student, "last_active", as_dict=1))
- get_progress_info(student, batch_courses)
- get_assessment_info(student, assessments)
-
- return sort_students(batch_students)
-
-
-def get_progress_info(student, batch_courses):
- courses_completed = 0
- student["courses"] = frappe._dict()
- for course in batch_courses:
- membership = get_membership(course.course, student.student)
- if membership and membership.progress == 100:
- courses_completed += 1
-
- student["courses_completed"] = courses_completed
- return student
-
-
-def get_assessment_info(student, assessments):
- assessments_completed = 0
- assessments_graded = 0
- for assessment in assessments:
- submission = has_submitted_assessment(
- assessment.assessment_name, assessment.assessment_type, student.student
- )
- if submission:
- assessments_completed += 1
-
- if (
- assessment.assessment_type == "LMS Assignment" and has_graded_assessment(submission)
- ):
- assessments_graded += 1
- elif assessment.assessment_type == "LMS Quiz":
- assessments_graded += 1
-
- student["assessments_completed"] = assessments_completed
- student["assessments_graded"] = assessments_graded
-
- return student
-
-
-def sort_students(batch_students):
- session_user = []
- remaining_students = []
-
- for student in batch_students:
- if student.student == frappe.session.user:
- session_user.append(student)
- else:
- remaining_students.append(student)
-
- if len(session_user):
- return session_user + remaining_students
- else:
- return batch_students
-
-
-def get_lesson_details(lesson, batch_name):
- lesson.update(
- frappe.db.get_value(
- "Course Lesson",
- lesson.lesson,
- ["name", "title", "body", "course", "chapter"],
- as_dict=True,
- )
- )
- lesson.index = get_lesson_index(lesson.lesson)
- lesson.url = get_lesson_url(lesson.course, lesson.index) + "?class=" + batch_name
- lesson.icon = get_lesson_icon(lesson.body)
- return lesson
-
-
-def get_current_student_details(batch_courses, batch_name):
- student_details = frappe._dict()
- student_details.courses = frappe._dict()
- course_list = [course.course for course in batch_courses]
-
- get_course_progress(batch_courses, student_details)
- student_details.name = frappe.session.user
- student_details.assessments = get_assessments(batch_name, frappe.session.user)
- student_details.upcoming_evals = get_upcoming_evals(frappe.session.user, course_list)
-
- return student_details
-
-
-def get_course_progress(batch_courses, student_details):
- for course in batch_courses:
- membership = get_membership(course.course, frappe.session.user)
- if membership:
- student_details.courses[course.course] = membership.progress
- else:
- student_details.courses[course.course] = 0
-
-
-def get_legends(batch):
- return frappe.get_all(
- "LMS Timetable Legend",
- filters={"parenttype": "LMS Batch", "parent": batch},
- fields=["reference_doctype", "color", "label"],
- )
diff --git a/lms/www/batches/batch_details.html b/lms/www/batches/batch_details.html
deleted file mode 100644
index 41ed8a3a..00000000
--- a/lms/www/batches/batch_details.html
+++ /dev/null
@@ -1,214 +0,0 @@
-{% extends "lms/templates/lms_base.html" %} {% block title %} {{
-_(batch_info.title) }} {% endblock %} {% block page_content %}
-
- {{ BatchHeader(batch_info) }}
-
- {{ BatchOverlay(batch_info, courses, students) }}
-
- {{ BatchDetails(batch_info) }} {{ CourseList(courses) }}
-
-
- {{ BatchDetailsRaw() }}
-
-{% endblock %} {% macro BatchHeader(batch_info) %}
-
-
-
- {{ BreadCrumb(batch_info) }} {{ BatchHeaderDetails(batch_info,
- courses, students) }}
-
-
-
-{% endmacro %} {% macro BreadCrumb(batch_info) %}
-
- {{ _("All Batches") }}
-
- {{ _("Batch Details") }}
-
-{% endmacro %} {% macro BatchHeaderDetails(batch_info, courses, students) %}
-
-
{{ batch_info.title }}
-
-
{{ batch_info.description }}
-
-
-
-
-
-
- {{ frappe.utils.format_date(batch_info.start_date, "long") }}
-
- {% if batch_info.start_date != batch_info.end_date %}
-
- - {{ frappe.utils.format_date(batch_info.end_date, "long") }}
-
- {% endif %}
-
-
- {% if batch_info.start_time and batch_info.end_time %}
-
-
-
-
-
- {{ frappe.utils.format_time(batch_info.start_time, "hh:mm a") }} -
-
-
- {{ frappe.utils.format_time(batch_info.end_time, "hh:mm a") }}
-
-
- {% endif %}
-
-{% endmacro %} {% macro BatchOverlay(batch_info, courses, students) %}
-
-
- {% if batch_info.seat_count %} {% if seats_left %}
-
- {{ _("Seats Available") }}: {{ seats_left }}
-
- {% else %}
-
- {{ _("No seats left") }}
-
- {% endif %} {% endif %} {% if batch_info.paid_batch %}
-
- {{ frappe.utils.fmt_money(batch_info.amount, 0, batch_info.currency)
- }}
-
- {% endif %}
-
-
-
-
-
- {{ courses | length }} {{ _("Courses") }}
-
-
-
-
-
-
-
- {{ frappe.utils.format_date(batch_info.start_date, "long") }}
-
- {% if batch_info.start_date != batch_info.end_date %}
-
- - {{ frappe.utils.format_date(batch_info.end_date, "long") }}
-
- {% endif %}
-
-
- {% if batch_info.start_time and batch_info.end_time %}
-
-
-
-
-
- {{ frappe.utils.format_time(batch_info.start_time, "hh:mm a") }}
- -
-
-
- {{ frappe.utils.format_time(batch_info.end_time, "hh:mm a") }}
-
-
- {% endif %}
-
-
- {% if is_moderator or is_evaluator %}
-
- {{ _("Manage Batch") }}
-
- {% elif batch_info.paid_batch and batch_info.start_date >
- frappe.utils.getdate() %}
-
- {{ _("Register Now") }}
-
- {% elif batch_info.allow_self_enrollment and batch_info.seat_count
- and seats_left and batch_info.start_date > frappe.utils.getdate() %}
-
- {{ _("Enroll Now") }}
-
- {% else %}
-
- {{ _("To join this batch, please contact the Administrator.") }}
-
- {% endif %}
-
- {% if is_moderator %}
-
- {% endif %}
-
-
-{% endmacro %} {% macro BatchDetails(batch_info) %}
-
{{ batch_info.batch_details }}
-{% endmacro %} {% macro CourseList(courses) %} {% if courses | length or
-is_moderator %}
-
-
-
{{ _("Courses") }}
- {% if is_moderator %}
-
- {{ _("Add Course") }}
-
- {% endif %}
-
-
- {% if courses | length %}
-
- {% for course in courses %}
-
- {% if is_moderator %}
-
-
-
-
-
-
-
-
-
-
-
-
- {% endif %} {{ widgets.CourseCard(course=course, read_only=False) }}
-
- {% endfor %}
-
- {% else %}
-
{{ _("No courses") }}
- {% endif %}
-
-{% endif %} {% endmacro %} {% macro BatchDetailsRaw() %} {% if
-batch_info.batch_details_raw %}
-
{{ batch_info.batch_details_raw }}
-{% endif %} {% endmacro %} {%- block script %} {{ super() }} {% if is_moderator
-%}
-
-{% endif %} {% endblock %}
diff --git a/lms/www/batches/batch_details.js b/lms/www/batches/batch_details.js
deleted file mode 100644
index 9e1eeeb5..00000000
--- a/lms/www/batches/batch_details.js
+++ /dev/null
@@ -1,129 +0,0 @@
-frappe.ready(() => {
- frappe.require("controls.bundle.js");
-
- $(".btn-add-course").click((e) => {
- show_course_modal(e);
- });
-
- $(".btn-edit-course").click((e) => {
- show_course_modal(e);
- });
-
- $(".btn-remove-course").click((e) => {
- remove_course(e);
- });
-
- $(".enroll-batch").click((e) => {
- enroll_batch(e);
- });
-});
-
-const show_course_modal = (e) => {
- const target = $(e.currentTarget);
- const course = target.data("course");
- const evaluator = target.data("evaluator");
- const course_name = target.data("name");
-
- let course_modal = new frappe.ui.Dialog({
- title: "Add Course",
- fields: [
- {
- fieldtype: "Link",
- options: "LMS Course",
- label: __("Course"),
- fieldname: "course",
- reqd: 1,
- only_select: 1,
- default: course || "",
- read_only: course ? 1 : 0,
- },
- {
- fieldtype: "Link",
- options: "Course Evaluator",
- label: __("Course Evaluator"),
- fieldname: "evaluator",
- only_select: 1,
- default: evaluator || "",
- },
- ],
- primary_action_label: __("Add"),
- primary_action(values) {
- add_course(values, course_name);
- course_modal.hide();
- },
- });
- course_modal.show();
- setTimeout(() => {
- $(".modal-body").css("min-height", "300px");
- }, 1000);
-};
-
-const enroll_batch = (e) => {
- let batch_name = $(".class-details").data("batch");
- if (frappe.session.user == "Guest") {
- window.location.href =
- "/login?redirect-to=/batches/details/" + batch_name;
- }
- frappe.call({
- method: "lms.lms.doctype.batch_student.batch_student.enroll_batch",
- args: {
- batch_name: batch_name,
- },
- callback(r) {
- frappe.show_alert(
- {
- message: __("Successfully Enrolled"),
- indicator: "green",
- },
- 2000
- );
- window.location.href = `/batches/${batch_name}`;
- },
- });
-};
-
-const add_course = (values, course_name) => {
- frappe.call({
- method: "lms.lms.doctype.lms_batch.lms_batch.add_course",
- args: {
- course: values.course,
- evaluator: values.evaluator,
- parent: $(".class-details").data("batch"),
- name: course_name || "",
- },
- callback(r) {
- frappe.show_alert(
- {
- message: course_name
- ? __("Course Updated")
- : __("Course Added"),
- indicator: "green",
- },
- 2000
- );
- window.location.reload();
- },
- });
-};
-
-const remove_course = (e) => {
- frappe.confirm("Are you sure you want to remove this course?", () => {
- frappe.call({
- method: "lms.lms.doctype.lms_batch.lms_batch.remove_course",
- args: {
- course: $(e.currentTarget).data("course"),
- parent: $(".class-details").data("batch"),
- },
- callback(r) {
- frappe.show_alert(
- {
- message: __("Course Removed"),
- indicator: "green",
- },
- 2000
- );
- window.location.reload();
- },
- });
- });
-};
diff --git a/lms/www/batches/batch_details.py b/lms/www/batches/batch_details.py
deleted file mode 100644
index 97f950d9..00000000
--- a/lms/www/batches/batch_details.py
+++ /dev/null
@@ -1,87 +0,0 @@
-import frappe
-from frappe import _
-from lms.lms.utils import (
- has_course_moderator_role,
- has_course_evaluator_role,
- check_multicurrency,
-)
-from lms.www.utils import is_student
-
-
-def get_context(context):
- context.no_cache = 1
- batch_name = frappe.form_dict["batchname"]
-
- context.batch_info = frappe.db.get_value(
- "LMS Batch",
- batch_name,
- [
- "name",
- "title",
- "description",
- "batch_details",
- "start_date",
- "end_date",
- "paid_batch",
- "amount",
- "currency",
- "category",
- "medium",
- "start_time",
- "end_time",
- "seat_count",
- "published",
- "meta_image",
- "batch_details_raw",
- "evaluation_end_date",
- "amount_usd",
- "allow_self_enrollment",
- ],
- as_dict=1,
- )
-
- if context.batch_info.amount and context.batch_info.currency:
- amount, currency = check_multicurrency(
- context.batch_info.amount,
- context.batch_info.currency,
- None,
- context.batch_info.amount_usd,
- )
- context.batch_info.amount = amount
- context.batch_info.currency = currency
-
- context.is_moderator = has_course_moderator_role()
- context.is_evaluator = has_course_evaluator_role()
- context.is_student = is_student(batch_name)
-
- if not context.is_moderator and not context.batch_info.published:
- raise frappe.PermissionError(_("You do not have permission to access this page."))
-
- if context.is_student:
- frappe.local.flags.redirect_location = f"/batches/{batch_name}"
- raise frappe.Redirect
-
- context.courses = frappe.get_all(
- "Batch Course",
- {"parent": batch_name},
- ["name as batch_course", "course", "title", "evaluator"],
- order_by="idx",
- )
-
- for course in context.courses:
- course.update(
- frappe.db.get_value(
- "LMS Course", course.course, ["name", "short_introduction", "image"], as_dict=1
- )
- )
-
- context.student_count = frappe.db.count("Batch Student", {"parent": batch_name})
- context.seats_left = context.batch_info.seat_count - context.student_count
-
- context.metatags = {
- "title": context.batch_info.title,
- "image": context.batch_info.meta_image,
- "description": context.batch_info.description,
- "keywords": context.batch_info.title,
- "og:type": "website",
- }
diff --git a/lms/www/batches/index.html b/lms/www/batches/index.html
deleted file mode 100644
index cdcd56eb..00000000
--- a/lms/www/batches/index.html
+++ /dev/null
@@ -1,209 +0,0 @@
-{% extends "lms/templates/lms_base.html" %}
-{% block title %}
- {{ _("All Batches") }}
-{% endblock %}
-
-{% block page_content %}
-
-
- {{ Header() }}
- {% if past_batches | length or upcoming_batches | length or private_batches | length %}
- {{ BatchTabs(past_batches, upcoming_batches, private_batches, my_batches) }}
- {% else %}
- {{ EmptyState() }}
- {% endif %}
-
-
-{% endblock %}
-
-{% macro Header() %}
-
-{% endmacro %}
-
-{% macro BatchTabs(past_batches, upcoming_batches, private_batches, my_batches) %}
-
-
-
-
-
-
-
- {{ BatchCard(upcoming_batches, show_price=True, label="Upcoming") }}
-
-
- {% if is_moderator %}
-
- {{ BatchCard(past_batches, show_price=False, label="Archived") }}
-
-
-
- {{ BatchCard(private_batches, show_price=False, label="Private") }}
-
- {% endif %}
-
- {% if frappe.session.user != "Guest" %}
-
- {{ BatchCard(my_batches, show_price=False, label="Enrolled") }}
-
- {% endif %}
-
-
-
-{% endmacro %}
-
-{% macro BatchCard(batches, show_price=False, label="") %}
-{% if batches | length %}
-
- {% for batch in batches %}
-
-
-
- {% if batch.seat_count %}
- {% if batch.seats_left > 0 %}
-
- {{ _("Seats Available") }}: {{ batch.seats_left }}
-
- {% else %}
-
- {{ _("No Seats Left") }}
-
- {% endif %}
- {% endif %}
-
-
- {{ batch.title }}
-
-
- {% if batch.description %}
-
- {{ batch.description }}
-
- {% endif %}
-
- {% if show_price and batch.paid_batch %}
-
- {{ frappe.utils.fmt_money(batch.amount, 0, batch.currency) }}
-
- {% endif %}
-
-
-
-
-
-
- {{ frappe.utils.format_date(batch.start_date, "medium") }}
-
- {% if batch.start_date != batch.end_date %}
-
- - {{ frappe.utils.format_date(batch.end_date, "long") }}
-
- {% endif %}
-
-
-
-
-
-
-
- {{ frappe.utils.format_time(batch.start_time, "HH:mm a") }} -
-
-
- {{ frappe.utils.format_time(batch.end_time, "HH:mm a") }}
-
-
-
-
-
-
-
- {{ batch.course_count }} {{ _("Courses") }}
-
-
- {% if is_student(batch.name) %}
-
- {% else %}
-
- {% endif %}
-
- {% endfor %}
-
-{% else %}
-
- {{ _("No {0} batches").format(label|lower) }}
-
-{% endif %}
-{% endmacro %}
-
-{% macro EmptyState() %}
-
-
-
-
{{ _("No Batches") }}
-
{{ _("Please contact the Administrator for more information.") }}
-
-
-{% endmacro %}
-
-{%- block script %}
- {{ super() }}
- {{ include_script('controls.bundle.js') }}
- {% if is_moderator %}
-
- {% endif %}
-{% endblock %}
diff --git a/lms/www/batches/index.py b/lms/www/batches/index.py
deleted file mode 100644
index 20d89bb6..00000000
--- a/lms/www/batches/index.py
+++ /dev/null
@@ -1,97 +0,0 @@
-import frappe
-from frappe.utils import getdate, get_time_str, nowtime
-from lms.lms.utils import (
- has_course_moderator_role,
- has_course_evaluator_role,
- check_multicurrency,
-)
-
-
-def get_context(context):
- context.no_cache = 1
- context.is_moderator = has_course_moderator_role()
- context.is_evaluator = has_course_evaluator_role()
- batches = frappe.get_all(
- "LMS Batch",
- fields=[
- "name",
- "title",
- "description",
- "start_date",
- "end_date",
- "start_time",
- "end_time",
- "paid_batch",
- "amount",
- "currency",
- "seat_count",
- "published",
- "amount_usd",
- ],
- order_by="start_date",
- )
-
- past_batches, upcoming_batches, private_batches = [], [], []
- for batch in batches:
- batch.student_count = frappe.db.count("Batch Student", {"parent": batch.name})
- batch.course_count = frappe.db.count("Batch Course", {"parent": batch.name})
-
- if batch.amount and batch.currency:
- amount, currency = check_multicurrency(
- batch.amount, batch.currency, None, batch.amount_usd
- )
- batch.amount = amount
- batch.currency = currency
-
- batch.seats_left = (
- batch.seat_count - batch.student_count if batch.seat_count else None
- )
- if not batch.published:
- private_batches.append(batch)
- elif getdate(batch.start_date) < getdate():
- past_batches.append(batch)
- elif (
- getdate(batch.start_date) == getdate() and get_time_str(batch.start_time) < nowtime()
- ):
- past_batches.append(batch)
- else:
- upcoming_batches.append(batch)
-
- context.past_batches = sorted(past_batches, key=lambda d: d.start_date, reverse=True)
- context.upcoming_batches = sorted(upcoming_batches, key=lambda d: d.start_date)
- context.private_batches = sorted(private_batches, key=lambda d: d.start_date)
-
- if frappe.session.user != "Guest":
- my_batches_info = []
- my_batches = frappe.get_all(
- "Batch Student", {"student": frappe.session.user}, pluck="parent"
- )
-
- for batch in my_batches:
- batchinfo = frappe.db.get_value(
- "LMS Batch",
- batch,
- [
- "name",
- "title",
- "description",
- "start_date",
- "end_date",
- "paid_batch",
- "amount",
- "currency",
- "seat_count",
- ],
- as_dict=True,
- )
-
- batchinfo.student_count = frappe.db.count(
- "Batch Student", {"parent": batchinfo.name}
- )
- batchinfo.course_count = frappe.db.count("Batch Course", {"parent": batchinfo.name})
- batchinfo.seats_left = batchinfo.seat_count - batchinfo.student_count
-
- my_batches_info.append(batchinfo)
- my_batches_info = sorted(my_batches_info, key=lambda d: d.start_date, reverse=True)
-
- context.my_batches = my_batches_info
diff --git a/lms/www/batches/progress.html b/lms/www/batches/progress.html
deleted file mode 100644
index 533f9c6c..00000000
--- a/lms/www/batches/progress.html
+++ /dev/null
@@ -1,92 +0,0 @@
-{% extends "lms/templates/lms_base.html" %}
-{% block title %}
- {{ student.first_name }}'s {{ _("Progress") }}
-{% endblock %}
-
-
-{% block page_content %}
-
- {{ Header() }}
-
- {{ Progress(batch, student) }}
-
-
-{% endblock %}
-
-{% macro Header() %}
-
-{% endmacro %}
-
-
-{% macro Progress(batch, student) %}
- {{ UpcomingEvals(upcoming_evals) }}
- {{ Assessments(batch, student) }}
-{% endmacro %}
-
-{% macro UpcomingEvals(upcoming_evals) %}
-
- {% include "lms/templates/upcoming_evals.html" %}
-
-{% endmacro %}
-
-{% macro Assessments(batch, student) %}
-
- {% include "lms/templates/assessments.html" %}
-
-
-{% endmacro %}
-
-{%- block script %}
- {{ super() }}
-
-{% endblock %}
\ No newline at end of file
diff --git a/lms/www/batches/progress.js b/lms/www/batches/progress.js
deleted file mode 100644
index 6b65f70a..00000000
--- a/lms/www/batches/progress.js
+++ /dev/null
@@ -1,45 +0,0 @@
-frappe.ready(() => {
- frappe.require("controls.bundle.js");
-
- $(".clickable-row").click((e) => {
- window.location.href = $(e.currentTarget).data("href");
- });
-
- $(".btn-certification").click((e) => {
- show_certificate_dialog(e);
- });
-});
-
-const show_certificate_dialog = (e) => {
- this.certificate_dialog = new frappe.ui.Dialog({
- title: __("Grant Certificate"),
- fields: [
- {
- fieldtype: "Link",
- fieldname: "course",
- label: __("Course"),
- options: "LMS Course",
- reqd: 1,
- filters: {
- name: ["in", courses],
- },
- filter_description: " ",
- only_select: 1,
- },
- {
- fieldtype: "Date",
- fieldname: "issue_date",
- label: __("Issue Date"),
- reqd: 1,
- default: frappe.datetime.get_today(),
- },
- {
- fieldtype: "Date",
- fieldname: "expiry_date",
- label: __("Expiry Date"),
- },
- ],
- });
-
- this.certificate_dialog.show();
-};
diff --git a/lms/www/batches/progress.py b/lms/www/batches/progress.py
deleted file mode 100644
index 230912e9..00000000
--- a/lms/www/batches/progress.py
+++ /dev/null
@@ -1,41 +0,0 @@
-import frappe
-from lms.lms.utils import (
- has_course_moderator_role,
- has_course_evaluator_role,
- get_upcoming_evals,
-)
-from frappe import _
-from lms.www.utils import get_assessments
-
-
-def get_context(context):
- context.no_cache = 1
-
- student = frappe.form_dict["username"]
- batch_name = frappe.form_dict["batchname"]
- context.is_moderator = has_course_moderator_role()
- context.is_evaluator = has_course_evaluator_role()
-
- context.student = frappe.db.get_value(
- "User",
- {"username": student},
- ["first_name", "full_name", "name", "last_active", "username"],
- as_dict=True,
- )
- if (
- not context.is_moderator
- and not context.is_evaluator
- and not context.student.name == frappe.session.user
- ):
- raise frappe.PermissionError(_("You don't have permission to access this page."))
-
- context.batch = frappe.db.get_value(
- "LMS Batch", batch_name, ["name", "title"], as_dict=True
- )
-
- context.courses = frappe.get_all(
- "Batch Course", {"parent": batch_name}, pluck="course"
- )
-
- context.assessments = get_assessments(batch_name, context.student.name)
- context.upcoming_evals = get_upcoming_evals(context.student.name, context.courses)
diff --git a/lms/www/billing/__init__.py b/lms/www/billing/__init__.py
deleted file mode 100644
index e69de29b..00000000
diff --git a/lms/www/billing/billing.html b/lms/www/billing/billing.html
deleted file mode 100644
index ae344328..00000000
--- a/lms/www/billing/billing.html
+++ /dev/null
@@ -1,75 +0,0 @@
-{% extends "lms/templates/lms_base.html" %}
-{% block title %}
- {{ title }} {{ _("Billing") }}
-{% endblock %}
-
-
-{% block page_content %}
-
-
- {{ Header() }}
- {{ Details() }}
- {{ BillingDetails() }}
-
-
-{% endblock %}
-
-{% macro Header() %}
-
-
- {{ _("Order Details") }}
-
-
- {{ _("Enter the billing information to complete the payment.").format(module) }}
-
-
-{% endmacro %}
-
-{% macro Details() %}
-
-
-
-
- {% set label = "Course" if module == "course" else "Batch" %}
- {{ _(label) }} : {{ title }}
-
-
-
-
-
- {{ _("Total Price: ") }}
- {{ frappe.utils.fmt_money(amount_with_gst, 2, currency) if gst_applied else frappe.utils.fmt_money(amount, 2, currency) }}
-
-
- {% if gst_applied %}
-
- {{ _("18% GST included") }}
-
- {% endif %}
-
-
-{% endmacro %}
-
-{% macro BillingDetails() %}
-
-
- {{ _("Billing Details") }}
-
-
-
- {{ "Proceed to Payment" }}
-
-
-{% endmacro %}
-
-{%- block script %}
-{{ super() }}
-
-
-{% endblock %}
diff --git a/lms/www/billing/billing.js b/lms/www/billing/billing.js
deleted file mode 100644
index 8e99c32f..00000000
--- a/lms/www/billing/billing.js
+++ /dev/null
@@ -1,246 +0,0 @@
-frappe.ready(() => {
- if ($("#billing-form").length) {
- frappe.require("controls.bundle.js", () => {
- setup_billing();
- });
- }
-
- $(".btn-pay").click((e) => {
- generate_payment_link(e);
- });
-});
-
-const setup_billing = () => {
- this.billing = new frappe.ui.FieldGroup({
- fields: [
- {
- fieldtype: "Data",
- label: __("Billing Name"),
- fieldname: "billing_name",
- reqd: 1,
- default: address && address.billing_name,
- },
- {
- fieldtype: "Data",
- label: __("Address Line 1"),
- fieldname: "address_line1",
- reqd: 1,
- default: address && address.address_line1,
- },
- {
- fieldtype: "Data",
- label: __("Address Line 2"),
- fieldname: "address_line2",
- default: address && address.address_line2,
- },
- {
- fieldtype: "Data",
- label: __("City/Town"),
- fieldname: "city",
- reqd: 1,
- default: address && address.city,
- },
- {
- fieldtype: "Data",
- label: __("State/Province"),
- fieldname: "state",
- default: address && address.state,
- },
- {
- fieldtype: "Column Break",
- },
- {
- fieldtype: "Link",
- label: __("Country"),
- fieldname: "country",
- options: "Country",
- reqd: 1,
- only_select: 1,
- default: address && address.country,
- change: () => {
- change_currency();
- },
- },
- {
- fieldtype: "Data",
- label: __("Postal Code"),
- fieldname: "pincode",
- reqd: 1,
- default: address && address.pincode,
- },
- {
- fieldtype: "Data",
- label: __("Phone Number"),
- fieldname: "phone",
- reqd: 1,
- default: address && address.phone,
- },
- {
- fieldtype: "Link",
- label: __("Where did you hear about this?"),
- fieldname: "source",
- options: "LMS Source",
- only_select: 1,
- reqd: 1,
- },
- {
- fieldtype: "Section Break",
- label: __("GST Details"),
- fieldname: "gst_details",
- depends_on: "eval:doc.country === 'India'",
- },
- {
- fieldtype: "Data",
- label: __("GSTIN"),
- fieldname: "gstin",
- },
- {
- fieldtype: "Column Break",
- fieldname: "gst_details_break",
- },
- {
- fieldtype: "Data",
- fieldname: "pan",
- label: __("PAN"),
- },
- ],
- body: $("#billing-form").get(0),
- });
- this.billing.make();
- $("#billing-form .form-section:last").removeClass("empty-section");
- $("#billing-form .frappe-control").removeClass("hide-control");
- $("#billing-form .form-column").addClass("p-0");
-};
-
-const generate_payment_link = (e) => {
- let new_address = this.billing.get_values();
- validate_address(new_address);
- let doctype = $(e.currentTarget).attr("data-doctype");
- let docname = decodeURIComponent($(e.currentTarget).attr("data-name"));
-
- frappe.call({
- method: "lms.lms.utils.get_payment_options",
- args: {
- doctype: doctype,
- docname: docname,
- phone: new_address.phone,
- country: new_address.country,
- },
- callback: (data) => {
- data.message.handler = (response) => {
- handle_success(
- response,
- doctype,
- docname,
- new_address,
- data.message.order_id
- );
- };
- let rzp1 = new Razorpay(data.message);
- rzp1.open();
- },
- });
-};
-
-const handle_success = (response, doctype, docname, address, order_id) => {
- frappe.call({
- method: "lms.lms.utils.verify_payment",
- args: {
- response: response,
- doctype: doctype,
- docname: docname,
- address: address,
- order_id: order_id,
- },
- callback: (data) => {
- frappe.show_alert({
- message: __("Payment Successful"),
- indicator: "green",
- });
- setTimeout(() => {
- window.location.href = data.message;
- }, 1000);
- },
- });
-};
-
-const change_currency = () => {
- $("#gst-message").removeClass("hide");
- let country = this.billing.get_value("country");
- if (exception_country.includes(country)) {
- update_price(original_price_formatted);
- return;
- }
- frappe.call({
- method: "lms.lms.utils.change_currency",
- args: {
- country: country,
- amount: amount,
- currency: currency,
- },
- callback: (data) => {
- let current_price = $(".total-price").text();
- if (current_price != data.message) {
- update_price(data.message);
- }
- if (data.message.includes("INR")) {
- $("#gst-message").removeClass("hide").addClass("show");
- } else {
- $("#gst-message").removeClass("show").addClass("hide");
- }
- },
- });
-};
-
-const update_price = (price) => {
- $(".total-price").text(price);
- frappe.show_alert({
- message: "Total Price has been updated.",
- indicator: "yellow",
- });
-};
-
-const validate_address = (billing_address) => {
- if (billing_address.country == "India" && !billing_address.state)
- frappe.throw(__("State is mandatory."));
-
- const states = [
- "Andhra Pradesh",
- "Arunachal Pradesh",
- "Assam",
- "Bihar",
- "Chhattisgarh",
- "Goa",
- "Gujarat",
- "Haryana",
- "Himachal Pradesh",
- "Jharkhand",
- "Karnataka",
- "Kerala",
- "Madhya Pradesh",
- "Maharashtra",
- "Manipur",
- "Meghalaya",
- "Mizoram",
- "Nagaland",
- "Odisha",
- "Punjab",
- "Rajasthan",
- "Sikkim",
- "Tamil Nadu",
- "Telangana",
- "Tripura",
- "Uttar Pradesh",
- "Uttarakhand",
- "West Bengal",
- ];
- if (
- billing_address.country == "India" &&
- !states.includes(billing_address.state)
- )
- frappe.throw(
- __(
- "Please enter a valid state with correct spelling and the first letter capitalized."
- )
- );
-};
diff --git a/lms/www/billing/billing.py b/lms/www/billing/billing.py
deleted file mode 100644
index edb21e98..00000000
--- a/lms/www/billing/billing.py
+++ /dev/null
@@ -1,121 +0,0 @@
-import frappe
-from frappe import _
-from lms.lms.utils import check_multicurrency, apply_gst
-
-
-def get_context(context):
- module = frappe.form_dict.module
- docname = frappe.form_dict.modulename
- doctype = "LMS Course" if module == "course" else "LMS Batch"
-
- context.module = module
- context.docname = docname
- context.doctype = doctype
-
- validate_access(doctype, docname, module)
- get_billing_details(context)
-
- context.original_currency = context.currency
- context.original_amount = (
- (context.amount * 1.18) if context.original_currency == "INR" else context.amount
- )
-
- context.exception_country = frappe.get_all(
- "Payment Country", filters={"parent": "LMS Settings"}, pluck="country"
- )
-
- context.amount, context.currency = check_multicurrency(
- context.amount, context.currency, None, context.amount_usd
- )
-
- context.address = get_address()
- if context.currency == "INR":
- context.amount_with_gst, context.gst_applied = apply_gst(context.amount, None)
-
-
-def validate_access(doctype, docname, module):
- if frappe.session.user == "Guest":
- raise frappe.PermissionError(_("Please login to continue with payment."))
-
- if module not in ["course", "batch"]:
- raise ValueError(_("Module is incorrect."))
-
- if not frappe.db.exists(doctype, docname):
- raise ValueError(_("Module Name is incorrect or does not exist."))
-
- if doctype == "LMS Course":
- membership = frappe.db.exists(
- "LMS Enrollment", {"member": frappe.session.user, "course": docname}
- )
- if membership:
- raise frappe.PermissionError(_("You are already enrolled for this course"))
-
- else:
- membership = frappe.db.exists(
- "Batch Student", {"student": frappe.session.user, "parent": docname}
- )
- if membership:
- raise frappe.PermissionError(_("You are already enrolled for this batch."))
-
-
-def get_billing_details(context):
- if context.doctype == "LMS Course":
- details = frappe.db.get_value(
- "LMS Course",
- context.docname,
- ["title", "name", "paid_course", "course_price as amount", "currency", "amount_usd"],
- as_dict=True,
- )
-
- if not details.paid_course:
- raise frappe.PermissionError(_("This course is free."))
-
- else:
- details = frappe.db.get_value(
- "LMS Batch",
- context.docname,
- ["title", "name", "paid_batch", "amount", "currency", "amount_usd"],
- as_dict=True,
- )
-
- if not details.paid_batch:
- raise frappe.PermissionError(
- _("To join this batch, please contact the Administrator.")
- )
-
- context.title = details.title
- context.amount = details.amount
- context.currency = details.currency
- context.amount_usd = details.amount_usd
-
-
-def get_address():
- address = frappe.get_all(
- "Address",
- {"email_id": frappe.session.user},
- [
- "address_title as billing_name",
- "address_line1",
- "address_line2",
- "city",
- "state",
- "country",
- "pincode",
- "phone",
- ],
- order_by="creation desc",
- limit=1,
- )
-
- if not len(address):
- return None
- else:
- address = address[0]
-
- if not address.address_line2:
- address.address_line2 = ""
-
- if not address.state:
- address.state = ""
-
- return address
diff --git a/lms/www/certified_participants/__init__.py b/lms/www/certified_participants/__init__.py
deleted file mode 100644
index e69de29b..00000000
diff --git a/lms/www/certified_participants/certified_participants.html b/lms/www/certified_participants/certified_participants.html
deleted file mode 100644
index f4e49cb3..00000000
--- a/lms/www/certified_participants/certified_participants.html
+++ /dev/null
@@ -1,63 +0,0 @@
-{% extends "lms/templates/lms_base.html" %}
-{% block title %}
- {{ _("Certified Participants") }}
-{% endblock %}
-
-{% block page_content %}
-
-
-
- {% if participants | length %}
- {{ ParticipantsList() }}
- {% else %}
- {{ EmptyState() }}
- {% endif %}
-
-
-
-{% endblock %}
-
-{% macro ParticipantsList() %}
-
- {% for participant in participants %}
-
- {{ widgets.Avatar(member=participant, avatar_class="avatar-large") }}
-
- {{ participant.full_name }}
-
- {% for course in participant.courses %}
-
- {{ course }}
-
- {% endfor %}
-
-
- {% endfor %}
-
-{% endmacro %}
-
-{% macro EmptyState() %}
-
-
-
-
{{ _("No Certified Participants") }}
-
{{ _("Enroll in a batch to get certified.") }}
-
-
-{% endmacro %}
\ No newline at end of file
diff --git a/lms/www/certified_participants/certified_participants.js b/lms/www/certified_participants/certified_participants.js
deleted file mode 100644
index af5b1340..00000000
--- a/lms/www/certified_participants/certified_participants.js
+++ /dev/null
@@ -1,18 +0,0 @@
-frappe.ready(() => {
- $("#certificate-filter").change((e) => {
- filter_certified_participants();
- });
-});
-
-const filter_certified_participants = () => {
- const certificate = $("#certificate-filter").val();
- $(".common-card-style").removeClass("hide");
-
- if (certificate) {
- $(".common-card-style").addClass("hide");
- $(`[data-course='${certificate}']`)
- .closest(".common-card-style")
- .removeClass("hide");
- console.log(certificate);
- }
-};
diff --git a/lms/www/certified_participants/certified_participants.py b/lms/www/certified_participants/certified_participants.py
deleted file mode 100644
index 2dc9b238..00000000
--- a/lms/www/certified_participants/certified_participants.py
+++ /dev/null
@@ -1,42 +0,0 @@
-import frappe
-
-
-def get_context(context):
- context.no_cache = 1
- members = frappe.get_all(
- "LMS Certificate",
- filters={"published": 1},
- pluck="member",
- order_by="issue_date desc",
- distinct=1,
- )
-
- participants = []
- course_filter = []
- for member in members:
- details = frappe.db.get_value(
- "User", member, ["name", "full_name", "user_image", "username", "enabled"], as_dict=1
- )
- courses = frappe.get_all(
- "LMS Certificate",
- filters={"member": member, "published": 1},
- fields=["course", "issue_date"],
- )
- details.courses = []
- for course in courses:
-
- if not details.issue_date:
- details.issue_date = course.issue_date
-
- title = frappe.db.get_value("LMS Course", course.course, "title")
- details.courses.append(title)
-
- if title not in course_filter:
- course_filter.append(title)
-
- if details.enabled:
- participants.append(details)
-
- participants = sorted(participants, key=lambda d: d.issue_date, reverse=True)
- context.participants = participants
- context.course_filter = course_filter
diff --git a/lms/www/classes/__init__.py b/lms/www/classes/__init__.py
deleted file mode 100644
index e69de29b..00000000
diff --git a/lms/www/cohorts/__init__.py b/lms/www/cohorts/__init__.py
deleted file mode 100644
index e69de29b..00000000
diff --git a/lms/www/cohorts/base.html b/lms/www/cohorts/base.html
deleted file mode 100644
index a1496f0e..00000000
--- a/lms/www/cohorts/base.html
+++ /dev/null
@@ -1,34 +0,0 @@
-{% extends "templates/base.html" %}
-
-{% macro render_nav(nav) %}
-
-
- {% for link in nav %}
-
{{ link.title }}
- {% if not loop.last %}
-
- {% endif %}
- {% endfor %}
-
-{% endmacro %}
-
-{% block title %}Cohorts{% endblock %}
-{% block head_include %}
-
-
-{% endblock %}
-
-
-{% block content %}
-
-
- {{ render_nav(nav | default([])) }}
-
- {% block page_content %}
- Hello, world!
- {% endblock %}
-
-
-{% endblock %}
-
-
diff --git a/lms/www/cohorts/cohort.html b/lms/www/cohorts/cohort.html
deleted file mode 100644
index 08f07988..00000000
--- a/lms/www/cohorts/cohort.html
+++ /dev/null
@@ -1,74 +0,0 @@
-{% extends "www/cohorts/base.html" %} {% block title %} {{ _("Manage") }} {{
-course.title }} {% endblock %} {% block page_content %}
-
{{ cohort.title }}
-{% if cohort.description %}
-
- {{ frappe.utils.md_to_html(cohort.description) }}
-
-{% endif %}
-
-
- {{ frappe.db.count("Cohort Subgroup", {"cohort": cohort.name}) }} {{
- _("Subgroups") }} | {{ frappe.db.count("Cohort Mentor", {"cohort":
- cohort.name}) }} {{ _("Mentors") }} | {{ frappe.db.count("LMS Enrollment",
- {"cohort": cohort.name}) }} {{ _("Students") }}
- | {{ frappe.db.count("Cohort Join Request", {"cohort": cohort.name}) }} {{ _("Join Requests") }}
-
-
-{% if is_mentor %} {% set sg = mentor.get_subgroup() %}
-
-{% endif %}
-
-
- {% set num_subgroups = cohort.get_subgroups() | length %} {{
- render_navitem("Subgroups", "", page=page, count=num_subgroups) }} {% for p
- in cohort.get_pages(scope="Cohort") %} {{ render_navitem(p.title, p.slug,
- page=page) }} {% endfor %}
-
-
-
- {% if not page %} {{ render_subgroups() }} {% else %} {{ render_page(page)
- }} {% endif %}
-
-
-{% endblock %} {% macro render_subgroups() %}
-
-{% endmacro %} {% macro render_navitem(title, link, page, count=-1) %}
-
-
- {{ title }} {% if count != -1 %}
-
- {{ count }}
-
- {% endif %}
-
-
-{% endmacro %}
diff --git a/lms/www/cohorts/cohort.py b/lms/www/cohorts/cohort.py
deleted file mode 100644
index fd0fb5d9..00000000
--- a/lms/www/cohorts/cohort.py
+++ /dev/null
@@ -1,34 +0,0 @@
-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
-
- 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")
-
- 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
- )
diff --git a/lms/www/cohorts/index.html b/lms/www/cohorts/index.html
deleted file mode 100644
index c9d4f287..00000000
--- a/lms/www/cohorts/index.html
+++ /dev/null
@@ -1,40 +0,0 @@
-{% extends "www/cohorts/base.html" %} {% block title %} _("Manage") {{
-course.title }} {% endblock %} {% block page_content %} {% if cohorts %}
-
{{ _("Cohorts") }}
-
- {% for cohort in cohorts %}
-
{{ render_cohort(course, cohort) }}
- {% endfor %}
-
-{% else %}
-
{{ _("Permission Denied") }}
-
{{ _("You don't have permission to manage this course.") }}
-{% endif %} {% endblock %} {% macro render_cohort(course, cohort) %}
-
-
-
{{ cohort.title }}
-
- {% if cohort.begin_date %}
-
- {{ frappe.utils.format_date(cohort.begin_date, "medium") }} - {{
- frappe.utils.format_date(cohort.end_date, "medium") }}
-
- {% endif %}
-
-
- {{ frappe.db.count("Cohort Subgroup", {"cohort": cohort.name}) }} {{
- _("Subgroups") }} | {{ frappe.db.count("Cohort Mentor", {"cohort":
- cohort.name}) }} {{ _("Mentors") }}
- | {{ frappe.db.count("LMS Enrollment", {"cohort": cohort.name}) }} {{ _("Students") }}
- | {{ frappe.db.count("Cohort Join Request", {"cohort": cohort.name}) }}
- {{ _("Join Requests") }}
-
-
-
-
-
-
-{% endmacro %}
diff --git a/lms/www/cohorts/index.py b/lms/www/cohorts/index.py
deleted file mode 100644
index 764c32e4..00000000
--- a/lms/www/cohorts/index.py
+++ /dev/null
@@ -1,41 +0,0 @@
-import frappe
-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()
-
- 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
-
- 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()
-
- 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]
diff --git a/lms/www/cohorts/join.html b/lms/www/cohorts/join.html
deleted file mode 100644
index 58fed3dd..00000000
--- a/lms/www/cohorts/join.html
+++ /dev/null
@@ -1,88 +0,0 @@
-{% extends "www/cohorts/base.html" %}
-
-{% block title %}{{ _("Join Course") }}{% endblock %}
-
-{% block page_content %}
-
-
{{ _("Join Course") }}
-
-
- Course: {{course.title}}
-
-
- Cohort: {{cohort.title}}
-
-
- Subgroup: {{subgroup.title}}
-
-
-{% if frappe.session.user == "Guest" %}
-
-
-{% elif subgroup.has_student(frappe.session.user) %}
-
-{% elif subgroup.has_join_request(frappe.session.user) %}
-
-
{{ _("We have received your request to join the course. You'll hear back from us soon.") }}
-
-{% else %}
-
-
{{ _("Join the course") }}
-
-{% endif %}
-
-{% endblock %}
-
-{% block script %}
-
-
-
-{% endblock %}
diff --git a/lms/www/cohorts/join.py b/lms/www/cohorts/join.py
deleted file mode 100644
index bfcba538..00000000
--- a/lms/www/cohorts/join.py
+++ /dev/null
@@ -1,26 +0,0 @@
-import frappe
-
-from . import utils
-
-
-def get_context(context):
- 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
-
- 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)
-
- context.course = course
- context.cohort = cohort
- context.subgroup = subgroup
diff --git a/lms/www/cohorts/subgroup.html b/lms/www/cohorts/subgroup.html
deleted file mode 100644
index af105cca..00000000
--- a/lms/www/cohorts/subgroup.html
+++ /dev/null
@@ -1,262 +0,0 @@
-{% extends "www/cohorts/base.html" %}
-{% block title %} Subgroup {{subgroup.title}} - {{ course.title }} {% endblock %}
-
-{% block page_content %}
-
- {{subgroup.title}}
-
-
-
- {{ render_navitem("Mentors", "/mentors", stats.mentors, page=="mentors")}}
- {{ render_navitem("Students", "/students", stats.students, page=="students")}}
- {% if is_mentor or is_admin %}
- {{ render_navitem("Join Requests", "/join-requests", stats.join_requests, page=="join-requests")}}
-
- {% for p in cohort.get_pages(scope="Subgroup") %}
- {{ render_navitem(p.title, "/" + p.slug, -1, page==p.slug) }}
- {% endfor %}
- {% endif %}
- {% if is_admin %}
- {{ render_navitem("Admin", "/admin", -1, page=="admin")}}
- {% endif %}
-
-
- {% if page == "info" %}
- {{ render_info() }}
- {% elif page == "mentors" %}
- {{ render_mentors() }}
- {% elif page == "students" %}
- {{ render_students() }}
- {% elif page == "join-requests" %}
- {{ render_join_requests() }}
- {% elif page == "admin" %}
- {{ render_admin() }}
- {% else %}
- {{ render_page(page) }}
- {% endif %}
-
-{% endblock %}
-
-{% macro render_admin() %}
-
-{% endmacro %}
-
-{% macro render_mentors() %}
- {% set mentors = subgroup.get_mentors() %}
- {% if mentors %}
-
- {% for m in mentors %}
- {{ widgets.MemberCard(member=m, avatar_class="avatar-medium", show_course_count=False) }}
- {% endfor %}
-
- {% else %}
-
None found.
- {% endif %}
-{% endmacro %}
-
-
-{% macro render_students() %}
- {% set students = subgroup.get_students() %}
- {% if students %}
-
- {% for student in students %}
- {{ widgets.MemberCard(member=student, avatar_class="avatar-medium", show_course_count=False) }}
- {% endfor %}
-
- {% else %}
-
None found.
- {% endif %}
-{% endmacro %}
-
-
-{% macro render_join_requests() %}
-
Invite Link
- {% set link = subgroup.get_invite_link() %}
-
{{link}}
-
- Copy to Clipboard
-
-
-{% set join_requests = subgroup.get_join_requests() %}
-
Pending Requests
- {% if join_requests %}
-
-
- #
- When
- Email
- Actions
-
- {% for r in join_requests %}
-
- {{loop.index}}
- {{r.creation}}
- {{r.email}}
-
- Approve | Reject
-
- {% endfor %}
-
- {% else %}
-
{{ _("There are no pending join requests.") }}
- {% endif %}
- {% set rejected_requests = subgroup.get_join_requests(status="Rejected") %}
-
-
Rejected Requests
- {% if rejected_requests %}
-
-
- #
- When
- Email
- Actions
-
- {% for r in rejected_requests %}
-
- {{loop.index}}
- {{r.creation}}
- {{r.email}}
-
- Undo
-
- {% endfor %}
-
- {% else %}
-
There are no rejected requests.
- {% endif %}
-{% endmacro %}
-
-{% macro render_navitem(title, link, count, active) %}
-
- {{title}}
- {% if count != -1 %}
- {{count}}
- {% endif %}
-
-
-{% endmacro %}
-
-
-{% block script %}
-
-
-{% endblock %}
-
-{% block style %}
-
-{% endblock %}
diff --git a/lms/www/cohorts/subgroup.py b/lms/www/cohorts/subgroup.py
deleted file mode 100644
index 51c2858c..00000000
--- a/lms/www/cohorts/subgroup.py
+++ /dev/null
@@ -1,73 +0,0 @@
-import frappe
-
-from . import utils
-
-
-def get_context(context):
- 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"])
-
- 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()
- )
-
- 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")]
-
- 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
-
- 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"
-
- # 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()),
- }
-
-
-def has_page(cohort, page):
- return cohort.get_page(page, scope="Subgroup")
diff --git a/lms/www/cohorts/utils.py b/lms/www/cohorts/utils.py
deleted file mode 100644
index e1d4ecfd..00000000
--- a/lms/www/cohorts/utils.py
+++ /dev/null
@@ -1,31 +0,0 @@
-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)
-
-
-def get_doc(doctype, name):
- 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)
-
-
-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)
-
-
-def add_nav(context, title, href):
- """Adds a breadcrumb to the navigation."""
- nav = context.setdefault("nav", [])
- nav.append({"title": title, "href": href})
diff --git a/lms/www/courses/__init__.py b/lms/www/courses/__init__.py
deleted file mode 100644
index e69de29b..00000000
diff --git a/lms/www/courses/__pycache__/__init__.py b/lms/www/courses/__pycache__/__init__.py
deleted file mode 100644
index e69de29b..00000000
diff --git a/lms/www/courses/certificate.html b/lms/www/courses/certificate.html
deleted file mode 100644
index 2a3af3d3..00000000
--- a/lms/www/courses/certificate.html
+++ /dev/null
@@ -1,71 +0,0 @@
-{% extends "templates/base.html" %}
-{% block title %} {{ member.full_name }} - {{ course.title }} {% endblock %}
-
-{% block content %}
-
-
-
-
-
-
-
-
- {{ final_template }}
-
-
-
- {% if doc.member == frappe.session.user or is_moderator %}
-
- {% endif %}
-
-
- {{ _("Certificate Recipient") }}:
-
-
-
- {{ widgets.Avatar(member=member, avatar_class="avatar-small") }}
-
- {{ member.full_name }}
-
-
-
-
- {{ _("Issued On") }}:
-
-
-
- {{ frappe.utils.format_date(doc.issue_date, "medium") }}
-
-
-
- {{ _("About the Course") }}:
-
-
-
- {{ course.title }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-{% endblock %}
diff --git a/lms/www/courses/certificate.py b/lms/www/courses/certificate.py
deleted file mode 100644
index 3b4839b4..00000000
--- a/lms/www/courses/certificate.py
+++ /dev/null
@@ -1,79 +0,0 @@
-import frappe
-from frappe import _
-from frappe.utils.jinja import render_template
-from frappe.utils import get_url
-from lms.lms.utils import has_course_moderator_role
-
-
-def get_context(context):
- context.no_cache = 1
-
- try:
- course_name = frappe.form_dict["course"]
- certificate_name = frappe.form_dict["certificate"]
- except KeyError:
- redirect_to_course_list()
-
- context.doc = frappe.db.get_value(
- "LMS Certificate",
- certificate_name,
- ["name", "member", "issue_date", "expiry_date", "course", "template"],
- as_dict=True,
- )
-
- if context.doc.course != course_name:
- redirect_to_course_list()
-
- context.course = frappe.db.get_value(
- "LMS Course", course_name, ["title", "name", "image"], as_dict=True
- )
- context.member = frappe.db.get_value(
- "User", context.doc.member, ["full_name", "username"], as_dict=True
- )
- context.url = f"{get_url()}/courses/{context.course.name}/{context.doc.name}"
- context.is_moderator = has_course_moderator_role()
-
- if context.doc.template:
- print_format = context.doc.template
- else:
- print_format = get_print_format()
-
- context.print_format = print_format
- template = frappe.db.get_value(
- "Print Format", print_format, ["html", "css"], as_dict=True
- )
- merged_template = "" + template.html
- final_template = render_template(merged_template, context)
- context.final_template = final_template
-
-
-def redirect_to_course_list():
- frappe.local.flags.redirect_location = "/courses"
- raise frappe.Redirect
-
-
-def get_print_format():
- print_format = None
- default = frappe.db.get_value(
- "Property Setter",
- {
- "doc_type": "LMS Certificate",
- "property": "default_print_format",
- },
- "value",
- )
-
- if frappe.db.exists("Print Format", default):
- print_format = default
-
- if not print_format and frappe.db.exists("Print Format", "Certificate"):
- print_format = "Certificate"
-
- if not print_format:
- raise ValueError(
- _(
- "Default Print Format is not set for Certificate. Please contact the Administrator."
- )
- )
-
- return print_format
diff --git a/lms/www/courses/course.html b/lms/www/courses/course.html
deleted file mode 100644
index b8f5b7fe..00000000
--- a/lms/www/courses/course.html
+++ /dev/null
@@ -1,286 +0,0 @@
-{% extends "lms/templates/lms_base.html" %}
-{% block title %}
- {{ course.title if course.title else _("New Course") }}
-{% endblock %}
-
-
-{% block page_content %}
-
-
- {{ CourseHomeHeader(course) }}
-
-
- {{ CourseHeaderOverlay(course) }}
-
- {{ Description(course) }}
- {{ widgets.CourseOutline(course=course, membership=membership, is_user_interested=is_user_interested) }}
- {% if course.status == "Approved" and not frappe.utils.cint(course.upcoming) %}
- {% include "lms/templates/reviews.html" %}
- {% endif %}
-
-
-
-
-
-{% endblock %}
-
-
-{% macro CourseHomeHeader(course) %}
-
-
-
- {{ BreadCrumb(course) }}
- {{ CourseCardWide(course) }}
-
-
-
-{% endmacro %}
-
-
-
-{% macro BreadCrumb(course) %}
-
-{% endmacro %}
-
-
-
-{% macro CourseCardWide(course) %}
-
- {% for tag in get_tags(course.name) %}
-
- {{ tag }}
-
- {% endfor %}
-
-
-
- {{ course.title }}
-
-
-
- {% if course.short_introduction %}
- {{ course.short_introduction }}
- {% endif %}
-
-
- {% if not course.upcoming %}
-
-
- {% for i in [1, 2, 3, 4, 5] %}
-
-
-
- {% endfor %}
-
-
- {% endif %}
-
-
-
{{ _("Instructors") }}:
- {% for instructor in get_instructors(course.name) %}
-
- {% endfor %}
-
-
- {% if membership %}
- {% set progress = frappe.utils.cint(membership.progress) %}
-
-
{{ progress }}% {{ _("Completed") }}
-
-
- {% endif %}
-{% endmacro %}
-
-
-
-{% macro CourseHeaderOverlay(course) %}
-
-
- {% if course.video_link %}
-
VIDEO
- {% endif %}
-
-
-
-
- {{ CTASection(course, membership) }}
-
-
- {{ Notes(course) }}
-
- {% if course.paid_course %}
-
- {{ frappe.utils.fmt_money(course.course_price, 0, course.currency) }}
-
- {% endif %}
-
-
-
-
-
- {{ format_number(get_students(course.name) | length) }} {{ _("Enrolled") }}
-
-
-
-
-
-
- {{ get_lessons(course.name, None, False) }} {{ _("Lessons") }}
-
-
-
-
-
-{% endmacro %}
-
-
-
-{% macro Description(course) %}
-
- {{ course.description }}
-
-{% endmacro %}
-
-
-
-
-{% macro RelatedCourses(course) %}
- {% if course.related_courses | length %}
-
- {% endif %}
-{% endmacro %}
-
-
-
-{% macro CTASection(course, membership) %}
- {% set lesson_index = get_lesson_index(membership.current_lesson) if membership and
- membership.current_lesson else "1.1" if first_lesson_exists(course.name) else None %}
-
-
- {% if is_instructor and not course.published and course.status != "Under Review" %}
-
- {{ _("Submit for Review") }}
-
-
- {% elif is_instructor and lesson_index %}
-
- {{ _("Checkout Course") }}
-
-
- {% elif course.upcoming and not is_user_interested and not is_instructor %}
-
- {{ _("Notify me when available") }}
-
-
- {% elif is_cohort_staff(course.name, frappe.session.user) %}
-
- {{ _("Manage Cohorts") }}
-
-
- {% elif membership %}
-
- {{ _("Continue Learning") }}
-
-
- {% elif course.paid_course and not is_instructor %}
-
- {{ _("Buy This Course") }}
-
-
- {% elif show_start_learing_cta(course, membership) %}
-
- {{ _("Start Learning") }}
-
- {% endif %}
-
- {% set progress = frappe.utils.cint(membership.progress) %}
-
- {% if membership and course.enable_certification %}
- {% if certificate %}
-
- {{ _("Get Certificate") }}
-
-
- {% elif course.grant_certificate_after == "Completion" and progress == 100 %}
-
- {{ _("Get Certificate") }}
-
- {% endif %}
- {% endif %}
-
- {% if is_instructor or has_course_moderator_role() %}
-
-
- {{ _("Edit") }}
-
- {% endif %}
-
-
-{% endmacro %}
-
-
-
-{% macro Notes(course) %}
-
- {{ _("You have opted to be notified for this course. You will receive an email when the course becomes available.") }}
-
-
- {% if course.status == "Under Review" and is_instructor %}
-
- {{ _("This course is currently under review. Once the review is complete, the System Admins will publish it on the website.") }}
-
- {% endif %}
-
- {% if no_of_attempts and no_of_attempts >= course.max_attempts %}
-
- {{ _("You have exceeded the maximum number of attempts allowed to appear for evaluations of this course.") }}
-
- {% endif %}
-{% endmacro %}
\ No newline at end of file
diff --git a/lms/www/courses/course.js b/lms/www/courses/course.js
deleted file mode 100644
index a3f86b84..00000000
--- a/lms/www/courses/course.js
+++ /dev/null
@@ -1,144 +0,0 @@
-frappe.ready(() => {
- hide_wrapped_mentor_cards();
-
- $(".review-link").click((e) => {
- show_review_dialog(e);
- });
-
- $(".icon-rating").click((e) => {
- highlight_rating(e);
- });
-
- $("#submit-review").click((e) => {
- submit_review(e);
- });
-
- $("#certification").click((e) => {
- create_certificate(e);
- });
-
- $("#submit-for-review").click((e) => {
- submit_for_review(e);
- });
-});
-
-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();
- }
-};
-
-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) {
- $(elem).addClass("star-click");
- }
- });
-};
-
-const submit_review = (e) => {
- e.preventDefault();
- let rating = $(".rating-field").children(".star-click").length;
- let 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");
- 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,
- },
- 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 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,
- },
- 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.`)
- );
- } else if (data.message == "OK") {
- frappe.show_alert(
- {
- message: __(
- "Your course has been submitted for review."
- ),
- indicator: "green",
- },
- 3
- );
- setTimeout(() => {
- window.location.reload();
- }, 1000);
- }
- },
- });
-};
diff --git a/lms/www/courses/course.py b/lms/www/courses/course.py
deleted file mode 100644
index 59314a6d..00000000
--- a/lms/www/courses/course.py
+++ /dev/null
@@ -1,119 +0,0 @@
-import frappe
-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,
- get_average_rating,
- check_multicurrency,
-)
-
-
-def get_context(context):
- context.no_cache = 1
-
- try:
- course_name = frappe.form_dict["course"]
- except KeyError:
- redirect_to_courses_list()
-
- if course_name == "new-course":
- if not can_create_courses(course_name):
- 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))
-
- context.course = frappe._dict()
- context.course.edit_mode = True
- context.membership = None
- else:
- set_course_context(context, course_name)
- context.avg_rating = get_average_rating(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",
- "paid_course",
- "course_price",
- "currency",
- "amount_usd",
- "enable_certification",
- "grant_certificate_after",
- ],
- as_dict=True,
- )
-
- if course.course_price:
- course.course_price, course.currency = check_multicurrency(
- course.course_price, course.currency, None, course.amount_usd
- )
-
- 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:
- raise frappe.PermissionError(_("This is not a valid course URL."))
-
- 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"],
- 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_old if membership and membership.batch_old else ""
- )
- context.membership = membership
- context.is_instructor = is_instructor(course.name)
- context.certificate = is_certified(course.name)
- eval_details = get_evaluation_details(course.name)
- context.eligible_for_evaluation = eval_details.eligible
- 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,
- "og:type": "website",
- }
-
-
-def get_user_interest(course):
- return frappe.db.count(
- "LMS Course Interest", {"course": course, "user": frappe.session.user}
- )
diff --git a/lms/www/courses/create.html b/lms/www/courses/create.html
deleted file mode 100644
index 8109085b..00000000
--- a/lms/www/courses/create.html
+++ /dev/null
@@ -1,216 +0,0 @@
-{% extends "lms/templates/lms_base.html" %}
-{% block title %}
- {{ course.title if course and course.title else _("New Course") }}
-{% endblock %}
-
-{% block page_content %}
-
- {{ Header() }}
-
- {{ CreateCourse() }}
-
-
-{% endblock %}
-
-
-{% macro Header() %}
-
-{% endmacro %}
-
-
-{% macro CreateCourse() %}
-
-
-
-
- {{ _("Title") }}
-
-
- {{ _("Something Short and Concise") }}
-
-
-
-
-
-
-
-
-
-
- {{ _("Short Introduction") }}
-
-
- {{ _("A one line brief description") }}
-
-
-
-
-
-
-
-
-
-
- {{ _("Course Description") }}
-
-
- {{ _("Add a detailed description to provide more information about your course.") }}
-
-
-
- {% if course.description %}
-
- {{ course.description }}
-
- {% endif %}
-
-
-
-
-
- {{ _("Preview Video ID") }}
-
-
- {{ _("Enter the Preview Video ID. The ID is the part of the URL after watch?v=. For example, if the URL is https://www.youtube.com/watch?v=QH2-TGUlwu4, the ID is QH2-TGUlwu4") }}
-
-
-
-
-
-
-
-
-
-
- {{ _("Tags") }}
-
-
- {{ _("Tags act as search keywords. They also appear on the Course Card and Course Detail page") }}
-
-
-
- {% for tag in get_tags(course.name) %}
-
- {{ tag }}
-
-
-
-
-
-
- {% endfor %}
-
-
-
-
- {% if is_moderator %}
-
-
-
- {{ _("Published") }}
-
-
-
- {{ _("Upcoming") }}
-
-
- {% endif %}
-
-
-
-
- {{ _("Course Image") }}
-
-
- {{ _("Image will appear on the Course Card") }}
-
-
-
-
- {{ _("Upload Image") }}
-
-
-
-
-
-
-
-
- {{ _("Paid Course") }}
-
-
-
-
-
- {{ _("Course Price") }}
-
-
- {{ _("The price of this course.") }}
-
-
-
-
-
-
-
-
- {{ _("Currency") }}
-
-
- {{ _("The currency in which users will pay for this course.") }}
-
-
-
-
- {% for currency in currencies %}
-
- {{ currency}}
-
- {% endfor %}
-
-
-
-
-
- {{ _("Instructor") }}
-
-
- {{ widgets.Avatar(member=member, avatar_class="avatar-medium") }}
-
- {{ member.full_name }}
-
-
-
-
-
-{% endmacro %}
-
-
-{%- block script %}
- {{ super() }}
- {{ include_script('controls.bundle.js') }}
-{% endblock %}
\ No newline at end of file
diff --git a/lms/www/courses/create.js b/lms/www/courses/create.js
deleted file mode 100644
index 64984e32..00000000
--- a/lms/www/courses/create.js
+++ /dev/null
@@ -1,191 +0,0 @@
-frappe.ready(() => {
- frappe.telemetry.capture("on_course_creation_page", "lms");
- $(".tags").click((e) => {
- e.preventDefault();
- $("#tags-input").focus();
- });
-
- $("#tags-input").focusout((e) => {
- create_tag(e);
- });
-
- $("#tags-input").focus((e) => {
- $(e.target).keypress((e) => {
- if (e.which == 13 || e.which == 44) {
- create_tag(e);
- setTimeout(() => {
- $("#tags-input").val("");
- }, 0);
- }
- });
- });
-
- $(document).on("click", ".btn-remove", (e) => {
- $(e.target).parent().parent().remove();
- });
-
- $(".btn-save-course").click((e) => {
- save_course(e);
- });
-
- if ($("#description").length) {
- make_editor();
- }
-
- $(".field-input").focusout((e) => {
- if ($(e.currentTarget).siblings(".error-message")) {
- $(e.currentTarget).siblings(".error-message").remove();
- }
- });
-
- $(".btn-upload").click((e) => {
- upload_file(e);
- });
-
- $("#paid-course").click((e) => {
- setup_paid_course(e);
- });
-});
-
-const create_tag = (e) => {
- if ($(e.target).val() == "") {
- return;
- }
-
- let tag_value = $(e.target)
- .val()
- .replace(//g, ">");
- let tag = `
- ${tag_value}
-
-
-
-
-
- `;
- $(tag).insertBefore("#tags-input");
- $(e.target).val("");
-};
-
-const save_course = (e) => {
- validate_mandatory();
- let tags = $(".tags button")
- .map((i, el) => $(el).text().trim())
- .get();
-
- frappe.call({
- method: "lms.lms.doctype.lms_course.lms_course.save_course",
- args: {
- tags: tags.join(", "),
- title: $("#title").val(),
- short_introduction: $("#intro").val(),
- video_link: $("#video-link").val(),
- image: $(".image-preview").attr("src"),
- description: this.description.fields_dict["description"].value,
- course: $("#title").data("course")
- ? $("#title").data("course")
- : "",
- published: $("#published").prop("checked") ? 1 : 0,
- upcoming: $("#upcoming").prop("checked") ? 1 : 0,
- paid_course: $("#paid-course").prop("checked") ? 1 : 0,
- course_price: $("#course-price").val(),
- currency: $("#currency").val(),
- },
- callback: (data) => {
- frappe.show_alert({
- message: __("Saved"),
- indicator: "green",
- });
- setTimeout(() => {
- window.location.href = `/courses/${data.message}/edit`;
- }, 1000);
- },
- });
-};
-
-const validate_mandatory = () => {
- let fields = $(".field-label.reqd");
- fields.each((i, el) => {
- let input = $(el).closest(".field-group").find(".field-input");
- if (input.length && input.val().trim() == "") {
- if (input.siblings(".error-message").length == 0) {
- scroll_to_element(input);
- throw_error(el, input);
- }
- throw `${$(el).text().trim()} is mandatory`;
- }
- });
-
- if (!strip_html(this.description.fields_dict["description"].value)) {
- scroll_to_element("#description");
- throw_error(
- "#description",
- this.description.fields_dict["description"].parent
- );
- throw "Description is mandatory";
- }
-};
-
-const throw_error = (el, input) => {
- let error = document.createElement("p");
- error.classList.add("error-message");
- error.innerText = `Please enter a ${$(el).text().trim()}`;
- $(error).insertAfter($(input));
-};
-
-const scroll_to_element = (element) => {
- if ($(element).length) {
- $([document.documentElement, document.body]).animate(
- {
- scrollTop: $(element).offset().top - 100,
- },
- 1000
- );
- }
-};
-
-const make_editor = () => {
- this.description = new frappe.ui.FieldGroup({
- fields: [
- {
- fieldname: "description",
- fieldtype: "Text Editor",
- default: $("#description-data").html(),
- },
- ],
- body: $("#description").get(0),
- });
- this.description.make();
- $("#description .form-section:last").removeClass("empty-section");
- $("#description .frappe-control").removeClass("hide-control");
- $("#description .form-column").addClass("p-0");
-};
-
-const upload_file = (e) => {
- new frappe.ui.FileUploader({
- disable_file_browser: true,
- folder: "Home/Attachments",
- make_attachments_public: true,
- restrictions: {
- allowed_file_types: ["image/*"],
- },
- on_success: (file_doc) => {
- $(e.target)
- .parent()
- .siblings("img")
- .addClass("image-preview")
- .attr("src", file_doc.file_url);
- },
- });
-};
-
-const setup_paid_course = (e) => {
- if ($(e.target).prop("checked")) {
- $(".price-field").removeClass("hide");
- $(".price-field").find(".field-label").addClass("reqd");
- } else {
- $(".price-field").addClass("hide");
- $(".price-field").find(".field-label").removeClass("reqd");
- }
-};
diff --git a/lms/www/courses/create.py b/lms/www/courses/create.py
deleted file mode 100644
index 746dfa09..00000000
--- a/lms/www/courses/create.py
+++ /dev/null
@@ -1,61 +0,0 @@
-import frappe
-from lms.lms.utils import (
- redirect_to_courses_list,
- can_create_courses,
- has_course_moderator_role,
- has_course_instructor_role,
-)
-from frappe import _
-
-
-def get_context(context):
- context.no_cache = 1
-
- try:
- course_name = frappe.form_dict["course"]
- except KeyError:
- redirect_to_courses_list()
-
- if not can_create_courses(course_name) and course_name != "new-course":
- 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))
-
- if course_name == "new-course" and has_course_instructor_role():
- context.course = frappe._dict()
- context.course.edit_mode = True
- context.membership = None
- elif not frappe.db.exists("LMS Course", course_name):
- redirect_to_courses_list()
- else:
- set_course_context(context, course_name)
-
- context.is_moderator = has_course_moderator_role()
- context.member = frappe.db.get_value(
- "User", frappe.session.user, ["full_name", "username"], as_dict=True
- )
- context.currencies = frappe.get_all("Currency", {"enabled": 1}, pluck="currency_name")
-
-
-def set_course_context(context, course_name):
- fields = [
- "name",
- "title",
- "short_introduction",
- "description",
- "image",
- "published",
- "upcoming",
- "disable_self_learning",
- "status",
- "video_link",
- "enable_certification",
- "grant_certificate_after",
- "paid_course",
- "course_price",
- "currency",
- "max_attempts",
- ]
- context.course = frappe.db.get_value("LMS Course", course_name, fields, as_dict=True)
diff --git a/lms/www/courses/index.html b/lms/www/courses/index.html
deleted file mode 100644
index 52ea23f7..00000000
--- a/lms/www/courses/index.html
+++ /dev/null
@@ -1,171 +0,0 @@
-{% extends "lms/templates/lms_base.html" %}
-
-
-{% block title %}
-{{ 'Courses' }}
-{% endblock %}
-
-
-{% block page_content %}
-
-
- {% if restriction %}
- {% set profile_link = "
profile " %}
-
-
- {{ _("You haven't completed your profile.") }}
-
-
- {{ _("Complete your {0} to access the courses.").format(profile_link) }}
-
-
-
- {% else %}
-
- {% include "lms/templates/search_course/search_course.html" %}
-
-
-
-
- {{ _("All Courses") }}
-
-
-
-
-
-
-
-
- {% set courses = live_courses %}
- {% set title = _("Live Courses") %}
- {% set classes = "live-courses" %}
- {% include "lms/templates/course_list.html" %}
-
-
-
- {% set courses = upcoming_courses %}
- {% set title = _("Upcoming Courses") %}
- {% set classes = "upcoming-courses" %}
- {% include "lms/templates/course_list.html" %}
-
-
- {% if frappe.session.user != "Guest" %}
-
- {% set courses = enrolled_courses %}
- {% set title = _("Enrolled Courses") %}
- {% set classes = "enrolled-courses" %}
- {% include "lms/templates/course_list.html" %}
-
- {% endif %}
-
- {% if show_creators_section %}
-
- {% set courses = created_courses %}
- {% set title = _("Created Courses") %}
- {% set classes = "created-courses" %}
- {% include "lms/templates/course_list.html" %}
-
- {% endif %}
-
- {% if show_review_section %}
-
- {% set courses = review_courses %}
- {% set title = _("Review Courses") %}
- {% set classes = "review-courses" %}
- {% include "lms/templates/course_list.html" %}
-
- {% endif %}
-
-
-
- {% endif %}
-
-
-{% endblock %}
diff --git a/lms/www/courses/index.py b/lms/www/courses/index.py
deleted file mode 100644
index 6670ca68..00000000
--- a/lms/www/courses/index.py
+++ /dev/null
@@ -1,90 +0,0 @@
-import frappe
-from frappe import _
-from lms.lms.utils import (
- check_profile_restriction,
- get_restriction_details,
- has_course_moderator_role,
- get_courses_under_review,
- get_average_rating,
- check_multicurrency,
- has_course_instructor_role,
-)
-from lms.overrides.user import get_enrolled_courses, get_authored_courses
-from frappe.utils.telemetry import capture
-
-
-def get_context(context):
- capture("active_site", "lms")
- context.no_cache = 1
- context.live_courses, context.upcoming_courses = get_courses()
- context.enrolled_courses = (
- get_enrolled_courses()["in_progress"] + get_enrolled_courses()["completed"]
- )
- context.created_courses = get_authored_courses(None, False)
- context.review_courses = get_courses_under_review()
- context.restriction = check_profile_restriction()
-
- portal_course_creation = frappe.db.get_single_value(
- "LMS Settings", "portal_course_creation"
- )
- context.show_creators_section = (
- True
- if portal_course_creation == "Anyone"
- or has_course_moderator_role()
- or has_course_instructor_role()
- else False
- )
- context.show_review_section = (
- has_course_moderator_role() and frappe.session.user != "Guest"
- )
-
- 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",
- }
-
-
-def get_courses():
- courses = frappe.get_all(
- "LMS Course",
- filters={"published": True},
- fields=[
- "name",
- "upcoming",
- "title",
- "short_introduction",
- "image",
- "paid_course",
- "course_price",
- "currency",
- "creation",
- "amount_usd",
- ],
- )
-
- live_courses, upcoming_courses = [], []
- for course in courses:
- course.enrollment_count = frappe.db.count(
- "LMS Enrollment", {"course": course.name, "member_type": "Student"}
- )
-
- if course.course_price:
- course.course_price, course.currency = check_multicurrency(
- course.course_price, course.currency, None, course.amount_usd
- )
-
- course.avg_rating = get_average_rating(course.name) or 0
- if course.upcoming:
- upcoming_courses.append(course)
- else:
- live_courses.append(course)
-
- live_courses.sort(key=lambda x: x.enrollment_count, reverse=True)
- upcoming_courses.sort(key=lambda x: x.enrollment_count, reverse=True)
-
- return live_courses, upcoming_courses
diff --git a/lms/www/courses/outline.html b/lms/www/courses/outline.html
deleted file mode 100644
index 2e662d81..00000000
--- a/lms/www/courses/outline.html
+++ /dev/null
@@ -1,194 +0,0 @@
-{% extends "lms/templates/lms_base.html" %}
-
-
-{% block title %}
-{{ _("Outline") }} - {{ course.title }}
-{% endblock %}
-
-{% block page_content %}
-
- {{ Header() }}
-
- {% if chapters | length %}
- {{ Outline(chapters) }}
- {% else %}
- {{ EmptyState() }}
- {% endif %}
- {{ CreateChapter() }}
-
-
-{% endblock %}
-
-
-{% macro Header() %}
-
-{% endmacro %}
-
-
-{% macro Outline(chapters) %}
- {% if chapters %}
-
- {% for chapter in chapters %}
- {% set chapter_index = loop.index %}
- {% set lessons = get_lessons(course.name, chapter) %}
-
-
-
-
-
-
-
-
- {{ chapter.title }}
-
-
-
- {% if chapter.description %}
-
- {{ chapter.description }}
-
- {% endif %}
-
- {% if lessons | length %}
-
- {% for lesson in lessons %}
-
- {% endfor %}
-
- {% endif %}
-
-
-
-
- {% endfor %}
-
- {% endif %}
-
-{% endmacro %}
-
-
-{% macro CreateChapter() %}
-
-
-
-
-
-
-
-
-
-
-
-
-
- {{ _("Chapter Title") }}
-
-
- {{ _("Something Short and Concise") }}
-
-
-
-
-
-
-
-
-
-
- {{ _("Short Description") }}
-
-
- {{ _("A brief description about this chapter.") }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-{% endmacro %}
-
-
-{% macro EmptyState() %}
-
-
-
- {{ _("You have not added any chapter yet") }}
-
-
- {{ _("Create and manage your chapters from here.") }}
-
-
-
-
- {{ _("Add Chapter") }}
-
-
-
-
-
-{% endmacro %}
\ No newline at end of file
diff --git a/lms/www/courses/outline.js b/lms/www/courses/outline.js
deleted file mode 100644
index eaf9fc6c..00000000
--- a/lms/www/courses/outline.js
+++ /dev/null
@@ -1,142 +0,0 @@
-frappe.ready(() => {
- frappe.telemetry.capture("on_course_outline_page", "lms");
- $(".btn-add-chapter").click((e) => {
- show_chapter_modal(e);
- });
-
- $(".edit-chapter").click((e) => {
- show_chapter_modal(e);
- });
-
- $("#save-chapter").click((e) => {
- save_chapter(e);
- });
-
- $(".lesson-dropzone").each((i, el) => {
- setSortable(el);
- });
-
- $(".chapter-dropzone").each((i, el) => {
- setSortable(el);
- });
-});
-
-const show_chapter_modal = (e) => {
- e.preventDefault();
- $("#chapter-modal").modal("show");
- let parent = $(e.currentTarget).closest(".chapter-container");
- if (parent) {
- $("#chapter-title").val($.trim(parent.find(".chapters-title").text()));
- $("#chapter-description").val(
- $.trim(parent.find(".chapter-description").text())
- );
- $("#chapter-modal").data("chapter", parent.data("chapter"));
- $("#chapter-modal").data("idx", parent.data("idx"));
- }
-};
-
-const save_chapter = (e) => {
- validate_mandatory();
- let parent = $("#chapter-modal");
-
- frappe.call({
- method: "lms.lms.doctype.lms_course.lms_course.save_chapter",
- args: {
- course: $("#course-outline").data("course"),
- title: $("#chapter-title").val(),
- chapter_description: $("#chapter-description").val(),
- idx: parent.data("idx") || $(".chapter-container").length,
- chapter: parent.data("chapter") || null,
- },
- callback: (data) => {
- $("#chapter-modal").modal("hide");
- frappe.show_alert({
- message: __("Saved"),
- indicator: "green",
- });
- setTimeout(() => {
- window.location.reload();
- }, 1000);
- },
- });
-};
-
-const validate_mandatory = () => {
- if (!$("#chapter-title").val()) {
- let error = $("p")
- .addClass("error-message")
- .text("Chapter title is required");
- $(error).insertAfter("#chapter-title");
- throw __("Chapter title is required");
- }
-};
-
-const setSortable = (el) => {
- new Sortable(el, {
- group: "drag",
- handle: ".drag-handle",
- animation: 150,
- fallbackOnBody: true,
- swapThreshold: 0.65,
- onEnd: (e) => {
- if ($(e.item).hasClass("outline-lesson")) reorder_lesson(e);
- else reorder_chapter(e);
- },
- onMove: (e) => {
- if (
- $(e.dragged).hasClass("outline-lesson") &&
- $(e.to).hasClass("chapter-dropzone")
- )
- return false;
- if (
- $(e.dragged).hasClass("chapter-edit") &&
- $(e.to).hasClass("lesson-dropzone")
- )
- return false;
- },
- });
-};
-
-const reorder_lesson = (e) => {
- let old_chapter = $(e.from).closest(".chapter-container").data("chapter");
- let new_chapter = $(e.to).closest(".chapter-container").data("chapter");
-
- if (old_chapter == new_chapter && e.oldIndex == e.newIndex) return;
-
- frappe.call({
- method: "lms.lms.doctype.lms_course.lms_course.reorder_lesson",
- args: {
- old_chapter: old_chapter,
- old_lesson_array: $(e.from)
- .children()
- .map((i, e) => $(e).data("lesson"))
- .get(),
- new_chapter: new_chapter,
- new_lesson_array: $(e.to)
- .children()
- .map((i, e) => $(e).data("lesson"))
- .get(),
- },
- callback: (data) => {
- window.location.reload();
- },
- });
-};
-
-const reorder_chapter = (e) => {
- if (e.oldIndex == e.newIndex) return;
-
- frappe.call({
- method: "lms.lms.doctype.lms_course.lms_course.reorder_chapter",
- args: {
- new_index: e.newIndex + 1,
- chapter_array: $(e.to)
- .children()
- .map((i, e) => $(e).data("chapter"))
- .get(),
- },
- callback: (data) => {
- window.location.reload();
- },
- });
-};
diff --git a/lms/www/courses/outline.py b/lms/www/courses/outline.py
deleted file mode 100644
index f01a71af..00000000
--- a/lms/www/courses/outline.py
+++ /dev/null
@@ -1,23 +0,0 @@
-import frappe
-from frappe import _
-from lms.lms.utils import get_chapters, can_create_courses, redirect_to_courses_list
-
-
-def get_context(context):
- context.no_cache = 1
- course_name = frappe.form_dict["course"]
-
- if not frappe.db.exists("LMS Course", course_name):
- redirect_to_courses_list()
-
- if not can_create_courses(course_name):
- 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))
-
- context.course = frappe.db.get_value(
- "LMS Course", course_name, ["name", "title"], as_dict=True
- )
- context.chapters = get_chapters(context.course.name)
diff --git a/lms/www/courses/utils.py b/lms/www/courses/utils.py
deleted file mode 100644
index e69de29b..00000000
diff --git a/lms/www/dashboard/__init__.py b/lms/www/dashboard/__init__.py
deleted file mode 100644
index e69de29b..00000000
diff --git a/lms/www/get_started/__init__.py b/lms/www/get_started/__init__.py
deleted file mode 100644
index e69de29b..00000000
diff --git a/lms/www/jobs_openings/__init__.py b/lms/www/jobs_openings/__init__.py
deleted file mode 100644
index e69de29b..00000000
diff --git a/lms/www/jobs_openings/index.html b/lms/www/jobs_openings/index.html
deleted file mode 100644
index 4d2642f8..00000000
--- a/lms/www/jobs_openings/index.html
+++ /dev/null
@@ -1,58 +0,0 @@
-{% extends "lms/templates/lms_base.html" %}
-{% block title %}{{ _('Job Openings') }}{% endblock %}
-
-
-{% block page_content %}
-
-
-
- {% if allow_posting %}
-
{{ _("Post a Job") }}
- {% endif %}
-
-
{{ _("{0}").format(title) }}
-
{{ _("{0}").format(subtitle) }}
-
- {% if jobs | length %}
-
- {% for job in jobs %}
-
- {% set company_logo = job.company_logo.replace(' ', '%20') %}
-
-
-
{{ _(job.job_title) }}
-
-
-
-
-
-
-
- {% endfor %}
-
-
- {% else %}
-
-
-
-
-
{{ _("No open jobs") }}
-
{{ _("There are no job openings at present.") }}
-
-
- {% endif %}
-
-
-{% endblock %}
diff --git a/lms/www/jobs_openings/index.py b/lms/www/jobs_openings/index.py
deleted file mode 100644
index 6dc2ae92..00000000
--- a/lms/www/jobs_openings/index.py
+++ /dev/null
@@ -1,13 +0,0 @@
-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")
diff --git a/lms/www/jobs_openings/job.html b/lms/www/jobs_openings/job.html
deleted file mode 100644
index f2b65889..00000000
--- a/lms/www/jobs_openings/job.html
+++ /dev/null
@@ -1,102 +0,0 @@
-{% extends "lms/templates/lms_base.html" %}
-{% block title %}{{ _(job.job_title) }}{% endblock %}
-
-
-{% block page_content %}
-
-
- {% if member.bio %}
- {{ member.bio }}
- {% else %}
- {{ _("Hey, my name is ") }} {{ member.full_name }}
- {% endif %}
-
-{% endmacro %}
-
-
-
-{% macro WorkPreference(member) %}
-