diff --git a/lms/hooks.py b/lms/hooks.py index 2ecdb1df..3e1e92d2 100644 --- a/lms/hooks.py +++ b/lms/hooks.py @@ -135,10 +135,10 @@ website_route_rules = [ {"from_route": "/sketches/", "to_route": "sketches/sketch"}, {"from_route": "/courses/", "to_route": "courses/course"}, {"from_route": "/courses//", "to_route": "courses/certificate"}, - {"from_route": "/hackathons/", "to_route": "hackathons/hackathon"}, - {"from_route": "/hackathons//", "to_route": "hackathons/project"}, {"from_route": "/courses//learn", "to_route": "batch/learn"}, {"from_route": "/courses//learn/.", "to_route": "batch/learn"}, + {"from_route": "/quizzes", "to_route": "batch/quiz_list"}, + {"from_route": "/quizzes/", "to_route": "batch/quiz"}, {"from_route": "/courses//progress", "to_route": "batch/progress"}, {"from_route": "/courses//join", "to_route": "batch/join"}, {"from_route": "/courses//manage", "to_route": "cohorts"}, @@ -190,7 +190,9 @@ jinja = { "lms.lms.utils.convert_number_to_character", "lms.lms.utils.get_signup_optin_checks", "lms.lms.utils.get_popular_courses", - "lms.lms.utils.format_amount" + "lms.lms.utils.format_amount", + "lms.lms.utils.first_lesson_exists", + "lms.lms.utils.has_course_instructor_role" ], "filters": [] } diff --git a/lms/job/doctype/job_opportunity/job_opportunity.json b/lms/job/doctype/job_opportunity/job_opportunity.json index aa712661..b0637b5f 100644 --- a/lms/job/doctype/job_opportunity/job_opportunity.json +++ b/lms/job/doctype/job_opportunity/job_opportunity.json @@ -1,5 +1,6 @@ { "actions": [], + "allow_import": 1, "allow_rename": 1, "autoname": "format: JOB-{#####}", "creation": "2022-02-07 12:01:41.074418", @@ -113,7 +114,7 @@ ], "index_web_pages_for_search": 1, "links": [], - "modified": "2022-02-24 12:37:45.666484", + "modified": "2022-07-28 13:41:29.224332", "modified_by": "Administrator", "module": "Job", "name": "Job Opportunity", diff --git a/lms/lms/doctype/course_lesson/course_lesson.js b/lms/lms/doctype/course_lesson/course_lesson.js index 453aaa58..f7722723 100644 --- a/lms/lms/doctype/course_lesson/course_lesson.js +++ b/lms/lms/doctype/course_lesson/course_lesson.js @@ -2,103 +2,128 @@ // For license information, please see license.txt frappe.ui.form.on('Course Lesson', { - setup: function (frm) { - frm.trigger('setup_help'); - }, - setup_help(frm) { - frm.get_field('help').html(` -

You can add some more additional content to the lesson using a special syntax. The table below mentions all types of dynamic content that you can add to the lessons and the syntax for the same.

-
-
- Content Type -
-
- Syntax -
-
+ setup: function (frm) { + frm.trigger('setup_help'); + }, + setup_help(frm) { + let quiz_link = ` ${__("Quiz List")} `; + let exercise_link = ` ${__("Exercise List")} `; + let file_link = ` ${__("File DocType")} `; -
-
- Video -
-
- {{ Video("url_of_source") }} -
-
- -
-
- YouTube Video -
-
- {{ YouTubeVideo("unique_embed_id") }} -
-
- -
-
- Exercise -
-
- {{ Exercise("exercise_name") }} -
-
- -
-
- Quiz -
-
- {{ Quiz("lms_quiz_name") }} -
-
- -
-
- Assignment -
-
- {{ Assignment("id-filetype") }} -
-
- -
- -
-
- Supported File Types for Assignment -
-
- Syntax -
-
- -
-
- .doc,.docx,.xml,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document -
-
- Document -
-
- -
-
- .pdf -
-
- PDF -
-
- -
-
- .png, .jpg, .jpeg -
-
- Image -
-
-`); - } + frm.get_field('help').html(` +

${__("You can add some more additional content to the lesson using a special syntax. The table below mentions all types of dynamic content that you can add to the lessons and the syntax for the same.")}

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ ${__("Content Type")} + + ${__("Syntax")} + + ${__("Description")} +
+ ${__("YouTube Video")} + + {{ YouTubeVideo("unique_embed_id") }} + + + ${ __("Copy and paste the syntax in the editor. Replace 'embed_src' with the embed source that YouTube provides. To get the source, follow the steps mentioned below.") } + +
    +
  • + ${ __("Upload the video on youtube.") } +
  • +
  • + ${ __("When you share a youtube video, it shows an option called Embed.") } +
  • +
  • + ${ __("On clicking it, it provides an iframe. Copy the source (src) of the iframe and paste it here.") } +
  • +
+
+ ${__("Quiz")} + + {{ Quiz("lms_quiz_id") }} + + ${ __("Copy and paste the syntax in the editor. Replace 'lms_quiz_id' with the ID of the Quiz you want to add. You can get the ID of the quiz from the {0}.", [quiz_link]) } +
+ ${__("Video")} + + {{ Video("url_of_source") }} + + ${ __("Upload a video from your local machine to the {0}. Copy and paste this syntax in the editor. Replace 'url_of_source' with the File URL field of the document you created in the File DocType.", [file_link]) } +
+ ${"Exercise"} + + {{ Exercise("exercise_id") }} + + ${ __("Copy and paste the syntax in the editor. Replace 'exercise_id' with the ID of the Exercise you want to add. You can get the ID of the exercise from the {0}.", [exercise_link]) } +
+ ${__("Assignment")} + + {{ Assignment("id-filetype") }} +
+
+ + + + + + + + + + + + + + + + +
+ ${__("Supported File Types for Assignment")} + + ${__("Syntax")} +
+ .doc, .docx, .xml + + ${__("Document")} +
+ .pdf + + ${__("PDF")} +
+ .png, .jpg, .jpeg + + ${__("Image")} +
+ `); + } }); diff --git a/lms/lms/doctype/course_lesson/course_lesson.py b/lms/lms/doctype/course_lesson/course_lesson.py index 04504d5e..ac639e24 100644 --- a/lms/lms/doctype/course_lesson/course_lesson.py +++ b/lms/lms/doctype/course_lesson/course_lesson.py @@ -29,7 +29,7 @@ class CourseLesson(Document): e = frappe.get_doc(doctype_map[section], name) e.lesson = self.name e.index_ = index - e.save() + e.save(ignore_permissions=True) index += 1 self.update_orphan_documents(doctype_map[section], documents) diff --git a/lms/lms/doctype/lms_course/lms_course.py b/lms/lms/doctype/lms_course/lms_course.py index 5e4a5df2..76b8e097 100644 --- a/lms/lms/doctype/lms_course/lms_course.py +++ b/lms/lms/doctype/lms_course/lms_course.py @@ -5,7 +5,7 @@ from __future__ import unicode_literals import frappe from frappe.model.document import Document import json -from ...utils import slugify +from ...utils import generate_slug from frappe.utils import flt, cint from lms.lms.utils import get_chapters @@ -59,22 +59,11 @@ class LMSCourse(Document): frappe.enqueue(method=frappe.sendmail, queue='short', timeout=300, is_async=True, **email_args) frappe.db.set_value("LMS Course Interest", user.name, "email_sent", True) - @staticmethod - def find(name): - """Returns the course with specified name. - """ - return find("LMS Course", published=True, name=name) def autoname(self): if not self.name: - self.name = self.generate_slug(title=self.title) + self.name = generate_slug(self.title, "LMS Course") - def generate_slug(self, title): - result = frappe.get_all( - 'LMS Course', - fields=['name']) - slugs = set([row['name'] for row in result]) - return slugify(title, used_slugs=slugs) def __repr__(self): return f"" @@ -203,3 +192,91 @@ def submit_for_review(course): return "No Chp" frappe.db.set_value("LMS Course", course, "status", "Under Review") return "OK" + + +@frappe.whitelist() +def save_course(tags, title, short_introduction, video_link, description, course, image=None): + if course: + doc = frappe.get_doc("LMS Course", course) + else: + doc = frappe.get_doc({ + "doctype": "LMS Course" + }) + + doc.update({ + "title": title, + "short_introduction": short_introduction, + "video_link": video_link, + "image": image, + "description": description, + "tags": tags + }) + doc.save(ignore_permissions=True) + return doc.name + + +@frappe.whitelist() +def save_chapter(course, title, chapter_description, idx, chapter): + if chapter: + doc = frappe.get_doc("Course Chapter", chapter) + else: + doc = frappe.get_doc({ + "doctype": "Course Chapter" + }) + + doc.update({ + "course": course, + "title": title, + "description": chapter_description + }) + doc.save(ignore_permissions=True) + + if chapter: + chapter_reference = frappe.get_doc("Chapter Reference", {"chapter": chapter}) + else: + chapter_reference = frappe.get_doc({ + "doctype": "Chapter Reference", + "parent": course, + "parenttype": "LMS Course", + "parentfield": "chapters", + "idx": idx + }) + + chapter_reference.update({"chapter": doc.name}) + chapter_reference.save(ignore_permissions=True) + + return doc.name + + +@frappe.whitelist() +def save_lesson(title, body, chapter, preview, idx, lesson): + if lesson: + doc = frappe.get_doc("Course Lesson", lesson) + else: + doc = frappe.get_doc({ + "doctype": "Course Lesson" + }) + + doc.update({ + "chapter": chapter, + "title": title, + "body": body, + "include_in_preview": preview + }) + doc.save(ignore_permissions=True) + + if lesson: + lesson_reference = frappe.get_doc("Lesson Reference", {"lesson": lesson}) + else: + lesson_reference = frappe.get_doc({ + "doctype": "Lesson Reference", + "parent": chapter, + "parenttype": "Course Chapter", + "parentfield": "lessons", + "idx": idx + }) + + lesson_reference.update({"lesson": doc.name}) + lesson_reference.save(ignore_permissions=True) + + return doc.name diff --git a/lms/lms/doctype/lms_quiz/lms_quiz.json b/lms/lms/doctype/lms_quiz/lms_quiz.json index e68caf67..99ffc184 100644 --- a/lms/lms/doctype/lms_quiz/lms_quiz.json +++ b/lms/lms/doctype/lms_quiz/lms_quiz.json @@ -2,7 +2,6 @@ "actions": [], "allow_import": 1, "allow_rename": 1, - "autoname": "field:title", "creation": "2021-06-07 10:50:17.893625", "doctype": "DocType", "editable_grid": 1, @@ -18,7 +17,9 @@ { "fieldname": "title", "fieldtype": "Data", + "in_list_view": 1, "label": "Title", + "reqd": 1, "unique": 1 }, { @@ -49,11 +50,10 @@ ], "index_web_pages_for_search": 1, "links": [], - "modified": "2022-05-16 14:47:55.364743", + "modified": "2022-08-19 17:54:41.685182", "modified_by": "Administrator", "module": "LMS", "name": "LMS Quiz", - "naming_rule": "By fieldname", "owner": "Administrator", "permissions": [ { diff --git a/lms/lms/doctype/lms_quiz/lms_quiz.py b/lms/lms/doctype/lms_quiz/lms_quiz.py index a4ad0e61..8b5f79cb 100644 --- a/lms/lms/doctype/lms_quiz/lms_quiz.py +++ b/lms/lms/doctype/lms_quiz/lms_quiz.py @@ -5,11 +5,20 @@ import frappe from frappe.model.document import Document import json from frappe import _ +from frappe.utils import cstr +from lms.lms.utils import generate_slug class LMSQuiz(Document): + + def autoname(self): + if not self.name: + self.name = generate_slug(self.title, "LMS Quiz") + + def validate(self): self.validate_correct_answers() + def validate_correct_answers(self): for question in self.questions: correct_options = self.get_correct_options(question) @@ -18,12 +27,14 @@ class LMSQuiz(Document): question.multiple = 1 if not len(correct_options): - frappe.throw(_("At least one answer must be correct for this question: {0}").format(frappe.bold(question.question))) + frappe.throw(_("At least one option must be correct for this question: {0}").format(frappe.bold(question.question))) + def get_correct_options(self, question): correct_option_fields = ["is_correct_1", "is_correct_2", "is_correct_3", "is_correct_4"] return list(filter(lambda x: question.get(x) == 1, correct_option_fields)) + def get_last_submission_details(self): """Returns the latest submission for this user. """ @@ -43,6 +54,7 @@ class LMSQuiz(Document): if result: return result[0] + @frappe.whitelist() def quiz_summary(quiz, results): score = 0 @@ -73,3 +85,45 @@ def quiz_summary(quiz, results): }).save(ignore_permissions=True) return score + + +@frappe.whitelist() +def save_quiz(quiz_title, questions, quiz): + if quiz: + doc = frappe.get_doc("LMS Quiz", quiz) + else: + doc = frappe.get_doc({ + "doctype": "LMS Quiz", + }) + + doc.update({ + "title": quiz_title + }) + doc.save(ignore_permissions=True) + + for index, row in enumerate(json.loads(questions)): + if row["question_name"]: + question_doc = frappe.get_doc("LMS Quiz Question", row["question_name"]) + else: + question_doc = frappe.get_doc({ + "doctype": "LMS Quiz Question", + "parent": doc.name, + "parenttype": "LMS Quiz", + "parentfield": "questions", + "idx": index + 1 + }) + + question_doc.update({ + "question": row["question"] + }) + + for num in range(1,5): + question_doc.update({ + "option_" + cstr(num): row["option_" + cstr(num)], + "explanation_" + cstr(num): row["explanation_" + cstr(num)], + "is_correct_" + cstr(num): row["is_correct_" + cstr(num)] + }) + + question_doc.save(ignore_permissions=True) + + return doc.name diff --git a/lms/lms/doctype/lms_quiz/test_lms_quiz.py b/lms/lms/doctype/lms_quiz/test_lms_quiz.py index e778aab8..ef004896 100644 --- a/lms/lms/doctype/lms_quiz/test_lms_quiz.py +++ b/lms/lms/doctype/lms_quiz/test_lms_quiz.py @@ -15,7 +15,7 @@ class TestLMSQuiz(unittest.TestCase): }).save(ignore_permissions=True) def test_with_multiple_options(self): - quiz = frappe.get_doc("LMS Quiz", "Test Quiz") + quiz = frappe.get_doc("LMS Quiz", "test-quiz") quiz.append("questions", { "question": "Question multiple", "option_1": "Option 1", @@ -27,7 +27,7 @@ class TestLMSQuiz(unittest.TestCase): self.assertTrue(quiz.questions[0].multiple) def test_with_no_correct_option(self): - quiz = frappe.get_doc("LMS Quiz", "Test Quiz") + quiz = frappe.get_doc("LMS Quiz", "test-quiz") quiz.append("questions", { "question": "Question no correct option", "option_1": "Option 1", @@ -37,5 +37,5 @@ class TestLMSQuiz(unittest.TestCase): @classmethod def tearDownClass(cls) -> None: - frappe.db.delete("LMS Quiz", "Test Quiz") - frappe.db.delete("LMS Quiz Question", {"parent": "Test Quiz"}) + frappe.db.delete("LMS Quiz", "test-quiz") + frappe.db.delete("LMS Quiz Question", {"parent": "test-quiz"}) diff --git a/lms/lms/doctype/lms_settings/lms_settings.json b/lms/lms/doctype/lms_settings/lms_settings.json index afbbbc1a..5e0fbbe9 100644 --- a/lms/lms/doctype/lms_settings/lms_settings.json +++ b/lms/lms/doctype/lms_settings/lms_settings.json @@ -6,8 +6,8 @@ "engine": "InnoDB", "field_order": [ "show_search", - "portal_course_creation", "force_profile_completion", + "portal_course_creation", "column_break_2", "search_placeholder", "custom_certificate_template", @@ -110,10 +110,11 @@ "fieldtype": "Column Break" }, { - "default": "0", + "default": "Course Instructor Role", "fieldname": "portal_course_creation", - "fieldtype": "Check", - "label": "Enable Course Creation from Portal" + "fieldtype": "Select", + "label": "Course Creation Access Through Website To", + "options": "Course Instructor Role\nAnyone" }, { "fieldname": "column_break_9", @@ -149,7 +150,7 @@ "index_web_pages_for_search": 1, "issingle": 1, "links": [], - "modified": "2022-05-09 09:55:24.519269", + "modified": "2022-08-22 10:02:59.988499", "modified_by": "Administrator", "module": "LMS", "name": "LMS Settings", diff --git a/lms/lms/utils.py b/lms/lms/utils.py index 129737fc..c8c8e28a 100644 --- a/lms/lms/utils.py +++ b/lms/lms/utils.py @@ -33,6 +33,15 @@ def slugify(title, used_slugs=[]): return new_slug count = count+1 + +def generate_slug(title, doctype): + result = frappe.get_all( + doctype, + fields=['name']) + slugs = set([row['name'] for row in result]) + return slugify(title, used_slugs=slugs) + + def get_membership(course, member, batch=None): filters = { "member": member, @@ -53,6 +62,8 @@ def get_membership(course, member, batch=None): def get_chapters(course): """Returns all chapters of this course. """ + if not course: + return [] chapters = frappe.get_all("Chapter Reference", {"parent": course}, ["idx", "chapter"], order_by="idx") for chapter in chapters: @@ -373,3 +384,26 @@ def format_amount(amount, currency): return amount precision = 0 if amount % 1000 == 0 else 1 return _("{0}k").format(fmt_money(amount_reduced, precision, currency)) + + +def first_lesson_exists(course): + first_chapter = frappe.db.get_value("Chapter Reference", {"parent": course, "idx": 1}, "name") + if not first_chapter: + return False + + first_lesson = frappe.db.get_value("Lesson Reference", {"parent": first_chapter, "idx": 1}, "name") + if not first_lesson: + return False + + return True + +def redirect_to_courses_list(): + frappe.local.flags.redirect_location = "/courses" + raise frappe.Redirect + + +def has_course_instructor_role(): + return frappe.db.get_value("Has Role", { + "parent": frappe.session.user, + "role": "Course Instructor" + }, "name") diff --git a/lms/lms/web_form/chapter/__init__.py b/lms/lms/web_form/chapter/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/lms/lms/web_form/chapter/chapter.js b/lms/lms/web_form/chapter/chapter.js deleted file mode 100644 index da98bb5e..00000000 --- a/lms/lms/web_form/chapter/chapter.js +++ /dev/null @@ -1,11 +0,0 @@ -frappe.ready(function() { - frappe.web_form.after_save = () => { - frappe.show_alert({ - message:__("Chapter has been saved successfully. Go back to the course and add this chapter to the chapters table."), - indicator:'green' - }, 3); - setTimeout(() => { - window.location.href = `/courses/${frappe.web_form.doc.course}`; - }, 3000); - } -}); diff --git a/lms/lms/web_form/chapter/chapter.json b/lms/lms/web_form/chapter/chapter.json deleted file mode 100644 index fc2b8afc..00000000 --- a/lms/lms/web_form/chapter/chapter.json +++ /dev/null @@ -1,89 +0,0 @@ -{ - "accept_payment": 0, - "allow_comments": 0, - "allow_delete": 0, - "allow_edit": 1, - "allow_incomplete": 0, - "allow_multiple": 1, - "allow_print": 0, - "amount": 0.0, - "amount_based_on_field": 0, - "apply_document_permissions": 1, - "button_label": "Save", - "creation": "2022-03-07 18:41:07.058806", - "doc_type": "Course Chapter", - "docstatus": 0, - "doctype": "Web Form", - "idx": 0, - "is_multi_step_form": 0, - "is_standard": 1, - "login_required": 1, - "max_attachment_size": 0, - "modified": "2022-03-14 18:48:01.704325", - "modified_by": "Administrator", - "module": "LMS", - "name": "chapter", - "owner": "Administrator", - "payment_button_label": "Buy Now", - "published": 1, - "route": "chapter", - "route_to_success_link": 0, - "show_attachments": 0, - "show_in_grid": 0, - "show_sidebar": 0, - "sidebar_items": [], - "success_url": "/chapter", - "title": "Chapter", - "web_form_fields": [ - { - "allow_read_on_all_link_options": 0, - "fieldname": "course", - "fieldtype": "Link", - "hidden": 0, - "label": "Course", - "max_length": 0, - "max_value": 0, - "options": "LMS Course", - "read_only": 0, - "reqd": 1, - "show_in_filter": 0 - }, - { - "allow_read_on_all_link_options": 0, - "fieldname": "title", - "fieldtype": "Data", - "hidden": 0, - "label": "Title", - "max_length": 0, - "max_value": 0, - "read_only": 0, - "reqd": 1, - "show_in_filter": 0 - }, - { - "allow_read_on_all_link_options": 0, - "fieldname": "description", - "fieldtype": "Small Text", - "hidden": 0, - "label": "Description", - "max_length": 0, - "max_value": 0, - "read_only": 0, - "reqd": 0, - "show_in_filter": 0 - }, - { - "allow_read_on_all_link_options": 0, - "fieldname": "lessons", - "fieldtype": "Table", - "hidden": 0, - "label": "Lessons", - "max_length": 0, - "max_value": 0, - "options": "Lesson Reference", - "read_only": 0, - "reqd": 0, - "show_in_filter": 0 - } - ] -} \ No newline at end of file diff --git a/lms/lms/web_form/chapter/chapter.py b/lms/lms/web_form/chapter/chapter.py deleted file mode 100644 index e1ada619..00000000 --- a/lms/lms/web_form/chapter/chapter.py +++ /dev/null @@ -1,5 +0,0 @@ -import frappe - -def get_context(context): - # do your magic here - pass diff --git a/lms/lms/web_form/course/__init__.py b/lms/lms/web_form/course/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/lms/lms/web_form/course/course.js b/lms/lms/web_form/course/course.js deleted file mode 100644 index ff539e0a..00000000 --- a/lms/lms/web_form/course/course.js +++ /dev/null @@ -1,6 +0,0 @@ -frappe.ready(function() { - frappe.web_form.after_save = () => { - let route = frappe.web_form.doc.name ? `/courses/${frappe.web_form.doc.name}` : `/course`; - window.location.href = route; - } -}); diff --git a/lms/lms/web_form/course/course.json b/lms/lms/web_form/course/course.json deleted file mode 100644 index f12d692e..00000000 --- a/lms/lms/web_form/course/course.json +++ /dev/null @@ -1,147 +0,0 @@ -{ - "accept_payment": 0, - "allow_comments": 0, - "allow_delete": 0, - "allow_edit": 1, - "allow_incomplete": 0, - "allow_multiple": 1, - "allow_print": 0, - "amount": 0.0, - "amount_based_on_field": 0, - "apply_document_permissions": 1, - "button_label": "Save", - "creation": "2022-03-07 14:40:41.262163", - "custom_css": "", - "doc_type": "LMS Course", - "docstatus": 0, - "doctype": "Web Form", - "idx": 0, - "is_multi_step_form": 0, - "is_standard": 1, - "login_required": 1, - "max_attachment_size": 0, - "modified": "2022-03-11 12:32:22.512115", - "modified_by": "Administrator", - "module": "LMS", - "name": "course", - "owner": "Administrator", - "payment_button_label": "Buy Now", - "published": 1, - "route": "course", - "route_to_success_link": 0, - "show_attachments": 0, - "show_in_grid": 0, - "show_sidebar": 0, - "sidebar_items": [], - "success_url": "/course", - "title": "Course", - "web_form_fields": [ - { - "allow_read_on_all_link_options": 0, - "fieldname": "title", - "fieldtype": "Data", - "hidden": 0, - "label": "Title", - "max_length": 0, - "max_value": 0, - "read_only": 0, - "reqd": 1, - "show_in_filter": 0 - }, - { - "allow_read_on_all_link_options": 0, - "fieldname": "tags", - "fieldtype": "Data", - "hidden": 0, - "label": "Tags", - "max_length": 0, - "max_value": 0, - "read_only": 0, - "reqd": 0, - "show_in_filter": 0 - }, - { - "allow_read_on_all_link_options": 0, - "fieldname": "", - "fieldtype": "Column Break", - "hidden": 0, - "max_length": 0, - "max_value": 0, - "read_only": 0, - "reqd": 0, - "show_in_filter": 0 - }, - { - "allow_read_on_all_link_options": 0, - "fieldname": "video_link", - "fieldtype": "Data", - "hidden": 0, - "label": "Video Embed Link", - "max_length": 0, - "max_value": 0, - "read_only": 0, - "reqd": 0, - "show_in_filter": 0 - }, - { - "allow_read_on_all_link_options": 0, - "fieldname": "image", - "fieldtype": "Attach Image", - "hidden": 0, - "label": "Preview Image", - "max_length": 0, - "max_value": 0, - "read_only": 0, - "reqd": 0, - "show_in_filter": 0 - }, - { - "allow_read_on_all_link_options": 0, - "fieldname": "", - "fieldtype": "Section Break", - "hidden": 0, - "max_length": 0, - "max_value": 0, - "read_only": 0, - "reqd": 0, - "show_in_filter": 0 - }, - { - "allow_read_on_all_link_options": 0, - "fieldname": "short_introduction", - "fieldtype": "Small Text", - "hidden": 0, - "label": "Short Introduction", - "max_length": 0, - "max_value": 0, - "read_only": 0, - "reqd": 1, - "show_in_filter": 0 - }, - { - "allow_read_on_all_link_options": 0, - "fieldname": "description", - "fieldtype": "Text", - "hidden": 0, - "label": "Description", - "max_length": 0, - "max_value": 0, - "read_only": 0, - "reqd": 1, - "show_in_filter": 0 - }, - { - "allow_read_on_all_link_options": 0, - "fieldname": "chapters", - "fieldtype": "Table", - "hidden": 0, - "label": "Chapters", - "max_length": 0, - "max_value": 0, - "options": "Chapter Reference", - "read_only": 0, - "reqd": 0, - "show_in_filter": 0 - } - ] -} \ No newline at end of file diff --git a/lms/lms/web_form/course/course.py b/lms/lms/web_form/course/course.py deleted file mode 100644 index e1ada619..00000000 --- a/lms/lms/web_form/course/course.py +++ /dev/null @@ -1,5 +0,0 @@ -import frappe - -def get_context(context): - # do your magic here - pass diff --git a/lms/lms/web_form/lesson/__init__.py b/lms/lms/web_form/lesson/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/lms/lms/web_form/lesson/lesson.js b/lms/lms/web_form/lesson/lesson.js deleted file mode 100644 index 82214a05..00000000 --- a/lms/lms/web_form/lesson/lesson.js +++ /dev/null @@ -1,97 +0,0 @@ -frappe.ready(function() { - - frappe.web_form.after_load = () => { - add_file_upload_component(); - fetch_course(); - }; - - frappe.web_form.after_save = () => { - show_success_message(); - }; - - $(document).on("click", ".add-attachment", (e) => { - show_upload_modal(); - }); - - $(document).on("click", ".copy-link", (e) => { - frappe.utils.copy_to_clipboard($(e.currentTarget).data("link")); - $(".attachments").collapse("hide"); - }); - -}); - -const fetch_course = () => { - frappe.call({ - method: "lms.lms.doctype.course_lesson.course_lesson.get_lesson_info", - args: { - "chapter": frappe.web_form.doc.chapter - }, - callback: (data) => { - this.course = data.message; - } - }); -} - -const show_upload_modal = () => { - new frappe.ui.FileUploader({ - folder: "Home/Attachments", - restrictions: { - allowed_file_types: ['image/*'] - }, - on_success: (file_doc) => { - $(".attachments").append(build_attachment_table(file_doc)); - let count = $(".attachment-count").data("count") + 1; - $(".attachment-count").data("count", count); - $(".attachment-count").html(__(`${count} attachments`)); - $(".attachments").removeClass("hide"); - }, - }); -}; - -const show_success_message = () => { - frappe.show_alert({ - message: __(`Lesson has been saved successfully. Go back to the chapter and add this lesson to the lessons table.`), - indicator:'green' - }, 3); - setTimeout(() => { - window.location.href = `/courses/${this.course}`; - }, 3000); -}; - -const add_file_upload_component = () => { - $(get_attachment_controls_html()).insertBefore($(`[data-fieldname="include_in_preview"]`).first()); -}; - -const get_attachment_controls_html = () => { - return ` -
-
- -
- - - - - {{ _("Upload Attachments") }} - -
-
-
-
- `; -}; - -const build_attachment_table = (file_doc) => { - return $(` - - ${file_doc.file_name} - {{ _("Copy Link") }} - - `); -}; diff --git a/lms/lms/web_form/lesson/lesson.json b/lms/lms/web_form/lesson/lesson.json deleted file mode 100644 index 346c4459..00000000 --- a/lms/lms/web_form/lesson/lesson.json +++ /dev/null @@ -1,91 +0,0 @@ -{ - "accept_payment": 0, - "allow_comments": 0, - "allow_delete": 0, - "allow_edit": 1, - "allow_incomplete": 0, - "allow_multiple": 1, - "allow_print": 0, - "amount": 0.0, - "amount_based_on_field": 0, - "apply_document_permissions": 1, - "button_label": "Save", - "creation": "2022-03-07 18:41:42.549831", - "custom_css": "#introduction {\n font-size: var(--text-base);\n}", - "doc_type": "Course Lesson", - "docstatus": 0, - "doctype": "Web Form", - "idx": 0, - "introduction_text": "
\n

Create lessons for your course. For adding content, use markdown syntax. You can add some additional content to the lesson using a special syntax. The table below mentions all types of dynamic content that you can add to the lessons and the syntax for the same.

\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
\n Content Type\n \n Syntax \n
Assignment {{ Assignment(\"id-filetype\") }}
Quiz {{ Quiz(\"lms_quiz_name\") }}
YouTube Video {{ YouTubeVideo(\"unique_embed_id\") }}
\n

Note: You can also attach videos from Vimeo by including the iframe embed of the video to the lesson.

\n
", - "is_multi_step_form": 0, - "is_standard": 1, - "login_required": 1, - "max_attachment_size": 0, - "modified": "2022-04-25 10:26:12.691050", - "modified_by": "Administrator", - "module": "LMS", - "name": "lesson", - "owner": "Administrator", - "payment_button_label": "Buy Now", - "published": 1, - "route": "lesson", - "route_to_success_link": 0, - "show_attachments": 0, - "show_in_grid": 0, - "show_sidebar": 0, - "sidebar_items": [], - "success_url": "", - "title": "Lesson", - "web_form_fields": [ - { - "allow_read_on_all_link_options": 0, - "fieldname": "chapter", - "fieldtype": "Link", - "hidden": 0, - "label": "Course Chapter", - "max_length": 0, - "max_value": 0, - "options": "Course Chapter", - "read_only": 0, - "reqd": 1, - "show_in_filter": 0 - }, - { - "allow_read_on_all_link_options": 0, - "fieldname": "title", - "fieldtype": "Data", - "hidden": 0, - "label": "Title", - "max_length": 0, - "max_value": 0, - "read_only": 0, - "reqd": 1, - "show_in_filter": 0 - }, - { - "allow_read_on_all_link_options": 0, - "default": "0", - "fieldname": "include_in_preview", - "fieldtype": "Check", - "hidden": 0, - "label": "Include In Preview", - "max_length": 0, - "max_value": 0, - "read_only": 0, - "reqd": 0, - "show_in_filter": 0 - }, - { - "allow_read_on_all_link_options": 0, - "fieldname": "body", - "fieldtype": "Text", - "hidden": 0, - "label": "Content", - "max_length": 0, - "max_value": 0, - "read_only": 0, - "reqd": 1, - "show_in_filter": 0 - } - ] -} \ No newline at end of file diff --git a/lms/lms/web_form/lesson/lesson.py b/lms/lms/web_form/lesson/lesson.py deleted file mode 100644 index e1ada619..00000000 --- a/lms/lms/web_form/lesson/lesson.py +++ /dev/null @@ -1,5 +0,0 @@ -import frappe - -def get_context(context): - # do your magic here - pass diff --git a/lms/lms/widgets/CourseOutline.html b/lms/lms/widgets/CourseOutline.html index 1aedcb2e..b146c3fd 100644 --- a/lms/lms/widgets/CourseOutline.html +++ b/lms/lms/widgets/CourseOutline.html @@ -1,185 +1,185 @@ -{% if get_chapters(course.name) | length %}
-
- {{ _("Course Content") }} -
- {% for chapter in get_chapters(course.name) %} -
-