From 0284c9305c59b757ee38715a08d2104e8e9815d1 Mon Sep 17 00:00:00 2001 From: pateljannat Date: Thu, 24 Jun 2021 10:25:23 +0530 Subject: [PATCH] fix: quiz progress and youtube video integration --- community/hooks.py | 10 +- community/lms/doctype/lesson/lesson.json | 13 +-- community/lms/doctype/lesson/lesson.py | 55 ++++++++--- .../lms/doctype/lms_course/lms_course.py | 8 +- community/lms/doctype/lms_quiz/lms_quiz.json | 11 ++- community/lms/doctype/lms_quiz/lms_quiz.py | 61 ++++++++++-- .../lms_quiz_question/lms_quiz_question.json | 98 ++++++++++++++++--- .../doctype/lms_quiz_questions/__init__.py | 0 .../lms_quiz_questions.json | 43 -------- .../lms_quiz_questions/lms_quiz_questions.py | 8 -- .../lms_quiz_result/lms_quiz_result.json | 16 +-- community/lms/widgets/BatchTabs.html | 16 +-- community/lms/widgets/ChapterTeaser.html | 47 +++------ community/lms/widgets/Quiz.html | 67 ------------- community/plugins.py | 23 +++++ community/public/css/style.less | 5 - community/templates/exercise.html | 10 ++ community/templates/quiz.html | 30 ++++++ community/www/batch/home.html | 2 +- community/www/batch/learn.html | 3 +- community/www/batch/learn.js | 52 ++++++++++ community/www/batch/utils.py | 2 +- community/www/courses/course.html | 3 +- community/www/courses/course.py | 11 ++- 24 files changed, 352 insertions(+), 242 deletions(-) delete mode 100644 community/lms/doctype/lms_quiz_questions/__init__.py delete mode 100644 community/lms/doctype/lms_quiz_questions/lms_quiz_questions.json delete mode 100644 community/lms/doctype/lms_quiz_questions/lms_quiz_questions.py delete mode 100644 community/lms/widgets/Quiz.html create mode 100644 community/templates/exercise.html create mode 100644 community/templates/quiz.html diff --git a/community/hooks.py b/community/hooks.py index 6d04ed83..eca23eac 100644 --- a/community/hooks.py +++ b/community/hooks.py @@ -161,10 +161,10 @@ whitelist = [ "/socket.io", "/hackathons", "/dashboard", - "/join-request" + "/join-request", "/add-a-new-batch", "/new-sign-up", - "/message" + "/message", "/about" ] whitelist_rules = [{"from_route": p, "to_route": p[1:]} for p in whitelist] @@ -188,4 +188,8 @@ update_website_context = 'community.widgets.update_website_context' # community_lesson_page_extension = None ## Markdown Macros for Lessons -# community_markdown_macro_renderers = {"Exercise": "myapp.mymodule.plugins.render_exercise"} +community_markdown_macro_renderers = { + "Exercise": "community.plugins.exercise_renderer", + "Quiz": "community.plugins.quiz_renderer", + "YouTubeVideo": "community.plugins.youtube_video_renderer", +} diff --git a/community/lms/doctype/lesson/lesson.json b/community/lms/doctype/lesson/lesson.json index f7222275..582596de 100644 --- a/community/lms/doctype/lesson/lesson.json +++ b/community/lms/doctype/lesson/lesson.json @@ -7,7 +7,6 @@ "engine": "InnoDB", "field_order": [ "chapter", - "lesson_type", "include_in_preview", "column_break_4", "title", @@ -24,14 +23,6 @@ "label": "Chapter", "options": "Chapter" }, - { - "default": "Video", - "fieldname": "lesson_type", - "fieldtype": "Select", - "in_list_view": 1, - "label": "Lesson Type", - "options": "Video\nText\nQuiz" - }, { "fieldname": "title", "fieldtype": "Data", @@ -73,7 +64,7 @@ ], "index_web_pages_for_search": 1, "links": [], - "modified": "2021-06-11 19:03:23.138165", + "modified": "2021-06-23 17:59:52.946515", "modified_by": "Administrator", "module": "LMS", "name": "Lesson", @@ -95,4 +86,4 @@ "sort_field": "modified", "sort_order": "DESC", "track_changes": 1 -} +} \ No newline at end of file diff --git a/community/lms/doctype/lesson/lesson.py b/community/lms/doctype/lesson/lesson.py index 53fe5d89..d90fa2c1 100644 --- a/community/lms/doctype/lesson/lesson.py +++ b/community/lms/doctype/lesson/lesson.py @@ -9,27 +9,35 @@ from ...md import markdown_to_html, find_macros class Lesson(Document): def before_save(self): - macros = find_macros(self.body) - exercises = [value for name, value in macros if name == "Exercise"] + dynamic_documents = ["Exercise", "Quiz"] + for section in dynamic_documents: + self.update_lesson_name_in_document(section) + def update_lesson_name_in_document(self, section): + doctype_map= { + "Exercise": "Exercise", + "Quiz": "LMS Quiz" + } + macros = find_macros(self.body) + documents = [value for name, value in macros if name == section] index = 1 - for name in exercises: - e = frappe.get_doc("Exercise", name) + for name in documents: + e = frappe.get_doc(doctype_map[section], name) e.lesson = self.name e.index_ = index e.save() index += 1 - self.update_orphan_exercises(exercises) + self.update_orphan_documents(doctype_map[section], documents) - def update_orphan_exercises(self, active_exercises): - """Updates the exercises that were previously part of this lesson, + def update_orphan_documents(self, doctype, documents): + """Updates the documents that were previously part of this lesson, but not any more. """ - linked_exercises = {row['name'] for row in frappe.get_all('Exercise', {"lesson": self.name})} - active_exercises = set(active_exercises) - orphan_exercises = linked_exercises - active_exercises - for name in orphan_exercises: - ex = frappe.get_doc("Exercise", name) + linked_documents = {row['name'] for row in frappe.get_all(doctype, {"lesson": self.name})} + active_documents = set(documents) + orphan_documents = linked_documents - active_documents + for name in orphan_documents: + ex = frappe.get_doc(doctype, name) ex.lesson = None ex.index_ = 0 ex.index_label = "" @@ -92,13 +100,30 @@ def update_progress(lesson): course_progress.save(ignore_permissions=True) def all_dynamic_content_submitted(lesson, user): + all_exercises_submitted = check_all_exercise_submission(lesson, user) + all_quiz_submitted = check_all_quiz_submitted(lesson, user) + return all_exercises_submitted and all_quiz_submitted + +def check_all_exercise_submission(lesson, user): exercise_names = frappe.get_list("Exercise", {"lesson": lesson}, pluck="name", ignore_permissions=True) - all_exercises_submitted = False + if not len(exercise_names): + return True query = { "exercise": ["in", exercise_names], "owner": user } if frappe.db.count("Exercise Submission", query) == len(exercise_names): - all_exercises_submitted = True + return True + return False - return all_exercises_submitted +def check_all_quiz_submitted(lesson, user): + quizzes = frappe.get_list("LMS Quiz", {"lesson": lesson}, pluck="name", ignore_permissions=True) + if not len(quizzes): + return True + query = { + "quiz": ["in", quizzes], + "owner": user + } + if frappe.db.count("LMS Quiz Submission", query) == len(quizzes): + return True + return False diff --git a/community/lms/doctype/lms_course/lms_course.py b/community/lms/doctype/lms_course/lms_course.py index 7f77cd5d..a98a5e63 100644 --- a/community/lms/doctype/lms_course/lms_course.py +++ b/community/lms/doctype/lms_course/lms_course.py @@ -199,13 +199,15 @@ class LMSCourse(Document): } if batch: filters["batch"] = batch - return frappe.db.get_value("LMS Batch Membership", filters, ["name","batch", "current_lesson"], as_dict=True) + membership = frappe.db.get_value("LMS Batch Membership", filters, ["name","batch", "current_lesson"], as_dict=True) + if membership and membership.batch: + membership.batch_title = frappe.db.get_value("LMS Batch", membership.batch, "title") + return membership - def get_all_memberships(self, member=frappe.session.user): + def get_all_memberships(self, member): all_memberships = frappe.get_all("LMS Batch Membership", {"member": member, "course": self.name}, ["batch"]) for membership in all_memberships: membership.batch_title = frappe.db.get_value("LMS Batch", membership.batch, "title") - print(all_memberships) return all_memberships def get_mentors(self, batch=None): diff --git a/community/lms/doctype/lms_quiz/lms_quiz.json b/community/lms/doctype/lms_quiz/lms_quiz.json index 3eb1222d..85cd2c42 100644 --- a/community/lms/doctype/lms_quiz/lms_quiz.json +++ b/community/lms/doctype/lms_quiz/lms_quiz.json @@ -7,7 +7,8 @@ "engine": "InnoDB", "field_order": [ "title", - "questions" + "questions", + "lesson" ], "fields": [ { @@ -21,11 +22,17 @@ "fieldtype": "Table", "label": "Questions", "options": "LMS Quiz Question" + }, + { + "fieldname": "lesson", + "fieldtype": "Link", + "label": "Lesson", + "options": "Lesson" } ], "index_web_pages_for_search": 1, "links": [], - "modified": "2021-06-07 12:22:37.333289", + "modified": "2021-06-23 17:58:57.642873", "modified_by": "Administrator", "module": "LMS", "name": "LMS Quiz", diff --git a/community/lms/doctype/lms_quiz/lms_quiz.py b/community/lms/doctype/lms_quiz/lms_quiz.py index 2d24280d..de002046 100644 --- a/community/lms/doctype/lms_quiz/lms_quiz.py +++ b/community/lms/doctype/lms_quiz/lms_quiz.py @@ -1,36 +1,79 @@ # Copyright (c) 2021, FOSS United and contributors # For license information, please see license.txt +from community.lms.doctype.lesson.lesson import update_progress import frappe from frappe.model.document import Document import json +from frappe import _ +from ..lesson.lesson import update_progress class LMSQuiz(Document): - pass + def validate(self): + self.validate_correct_answers() + + def validate_correct_answers(self): + for question in self.questions: + correct_options = self.get_correct_options(question) + + if len(correct_options) > 1: + 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))) + + 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. + """ + user = frappe.session.user + if not user or user == "Guest": + return + + result = frappe.get_all('LMS Quiz Submission', + fields="*", + filters={ + "owner": user, + "quiz": self.name + }, + order_by="creation desc", + page_length=1) + + if result: + return result[0] @frappe.whitelist() def submit(quiz, result): score = 0 + answer_map = { + "is_correct_1": "option_1", + "is_correct_2": "option_2", + "is_correct_3": "option_3", + "is_correct_4": "option_4" + } result = json.loads(result) quiz_details = frappe.get_doc("LMS Quiz", quiz) - print(result, type(result)) + for response in result: match = list(filter(lambda x: x.question == response.get("question"), quiz_details.questions))[0] - response["users_response"] = ("").join([ ans for ans in response.get("answer") ]).replace(" ", ", ") - del response["answer"] - print(response.get("users_response"), match.answer) - if response.get("users_response") == match.answer: + correct_options = quiz_details.get_correct_options(match) + correct_answers = [ match.get(answer_map[option]) for option in correct_options ] + + if response.get("answer") == correct_answers: response["result"] = "Right" score += 1 else: response["result"] = "Wrong" + response["answer"] = ("").join([ ans if idx == len(response.get("answer")) -1 else ans + ", " for idx, ans in enumerate(response.get("answer")) ]) frappe.get_doc({ "doctype": "LMS Quiz Submission", "quiz": quiz, "result": result, "score": score - }).save() + }).save(ignore_permissions=True) + update_progress(quiz_details.lesson) return score - - diff --git a/community/lms/doctype/lms_quiz_question/lms_quiz_question.json b/community/lms/doctype/lms_quiz_question/lms_quiz_question.json index d861b138..b42c6bad 100644 --- a/community/lms/doctype/lms_quiz_question/lms_quiz_question.json +++ b/community/lms/doctype/lms_quiz_question/lms_quiz_question.json @@ -6,41 +6,107 @@ "engine": "InnoDB", "field_order": [ "question", - "options", - "answer", - "multiple_correct_answers" + "options_section", + "option_1", + "is_correct_1", + "section_break_5", + "option_2", + "is_correct_2", + "column_break_4", + "option_3", + "is_correct_3", + "section_break_11", + "option_4", + "is_correct_4", + "multiple" ], "fields": [ { "fieldname": "question", "fieldtype": "Text", "in_list_view": 1, - "label": "Question" + "label": "Question", + "reqd": 1 }, { - "fieldname": "options", - "fieldtype": "Text", - "in_list_view": 1, - "label": "Options" + "fieldname": "option_1", + "fieldtype": "Data", + "label": "Option 1", + "reqd": 1 + }, + { + "fieldname": "option_2", + "fieldtype": "Data", + "label": "Option 2", + "reqd": 1 + }, + { + "fieldname": "option_3", + "fieldtype": "Data", + "label": "Option 3" + }, + { + "fieldname": "option_4", + "fieldtype": "Data", + "label": "Option 4" }, { "default": "0", - "fieldname": "multiple_correct_answers", + "depends_on": "option_1", + "fieldname": "is_correct_1", "fieldtype": "Check", - "in_list_view": 1, - "label": "Multiple Correct Answers" + "label": "Is Correct" }, { - "fieldname": "answer", - "fieldtype": "Data", - "in_list_view": 1, - "label": "Answer" + "default": "0", + "depends_on": "option_2", + "fieldname": "is_correct_2", + "fieldtype": "Check", + "label": "Is Correct" + }, + { + "default": "0", + "depends_on": "option_3", + "fieldname": "is_correct_3", + "fieldtype": "Check", + "label": "Is Correct" + }, + { + "default": "0", + "depends_on": "option_4", + "fieldname": "is_correct_4", + "fieldtype": "Check", + "label": "Is Correct" + }, + { + "default": "0", + "fieldname": "multiple", + "fieldtype": "Check", + "hidden": 1, + "label": "Multiple Correct Answers", + "read_only": 1 + }, + { + "fieldname": "options_section", + "fieldtype": "Section Break" + }, + { + "fieldname": "column_break_4", + "fieldtype": "Section Break" + }, + { + "fieldname": "section_break_5", + "fieldtype": "Section Break" + }, + { + "fieldname": "section_break_11", + "fieldtype": "Section Break" } ], "index_web_pages_for_search": 1, "istable": 1, "links": [], - "modified": "2021-06-07 12:47:22.787160", + "modified": "2021-06-22 16:54:13.133859", "modified_by": "Administrator", "module": "LMS", "name": "LMS Quiz Question", diff --git a/community/lms/doctype/lms_quiz_questions/__init__.py b/community/lms/doctype/lms_quiz_questions/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/community/lms/doctype/lms_quiz_questions/lms_quiz_questions.json b/community/lms/doctype/lms_quiz_questions/lms_quiz_questions.json deleted file mode 100644 index 4e147664..00000000 --- a/community/lms/doctype/lms_quiz_questions/lms_quiz_questions.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "actions": [], - "creation": "2021-06-07 10:48:57.994714", - "doctype": "DocType", - "editable_grid": 1, - "engine": "InnoDB", - "field_order": [ - "question", - "options", - "multiple_correct_answers" - ], - "fields": [ - { - "fieldname": "question", - "fieldtype": "Data", - "label": "Question" - }, - { - "fieldname": "options", - "fieldtype": "Table", - "label": "Options", - "options": "LMS Option" - }, - { - "default": "0", - "fieldname": "multiple_correct_answers", - "fieldtype": "Check", - "label": "Multiple Correct Answers" - } - ], - "index_web_pages_for_search": 1, - "istable": 1, - "links": [], - "modified": "2021-06-07 10:48:57.994714", - "modified_by": "Administrator", - "module": "LMS", - "name": "LMS Quiz Questions", - "owner": "Administrator", - "permissions": [], - "sort_field": "modified", - "sort_order": "DESC", - "track_changes": 1 -} \ No newline at end of file diff --git a/community/lms/doctype/lms_quiz_questions/lms_quiz_questions.py b/community/lms/doctype/lms_quiz_questions/lms_quiz_questions.py deleted file mode 100644 index f1d7948e..00000000 --- a/community/lms/doctype/lms_quiz_questions/lms_quiz_questions.py +++ /dev/null @@ -1,8 +0,0 @@ -# Copyright (c) 2021, FOSS United and contributors -# For license information, please see license.txt - -# import frappe -from frappe.model.document import Document - -class LMSQuizQuestions(Document): - pass diff --git a/community/lms/doctype/lms_quiz_result/lms_quiz_result.json b/community/lms/doctype/lms_quiz_result/lms_quiz_result.json index 12346e2f..255b8a9a 100644 --- a/community/lms/doctype/lms_quiz_result/lms_quiz_result.json +++ b/community/lms/doctype/lms_quiz_result/lms_quiz_result.json @@ -6,7 +6,7 @@ "engine": "InnoDB", "field_order": [ "question", - "users_response", + "answer", "result" ], "fields": [ @@ -16,24 +16,24 @@ "in_list_view": 1, "label": "Question" }, - { - "fieldname": "users_response", - "fieldtype": "Data", - "in_list_view": 1, - "label": "Users Response" - }, { "fieldname": "result", "fieldtype": "Select", "in_list_view": 1, "label": "Result", "options": "Right\nWrong" + }, + { + "fieldname": "answer", + "fieldtype": "Data", + "in_list_view": 1, + "label": "Users Response" } ], "index_web_pages_for_search": 1, "istable": 1, "links": [], - "modified": "2021-06-07 14:21:07.768039", + "modified": "2021-06-22 18:32:28.813159", "modified_by": "Administrator", "module": "LMS", "name": "LMS Quiz Result", diff --git a/community/lms/widgets/BatchTabs.html b/community/lms/widgets/BatchTabs.html index 1b6d61d9..07c4c71a 100644 --- a/community/lms/widgets/BatchTabs.html +++ b/community/lms/widgets/BatchTabs.html @@ -2,16 +2,17 @@ Courses /{% if course.is_mentor(frappe.session.user) %} {{ course.title }} {% else %} {{ course.title }} {% endif %} - {% set all_memberships = course.get_all_memberships() %} - {% if all_memberships | length > 1 %} - @@ -28,7 +29,8 @@ Home diff --git a/community/lms/widgets/ChapterTeaser.html b/community/lms/widgets/ChapterTeaser.html index b4a0179f..5a49f5b3 100644 --- a/community/lms/widgets/ChapterTeaser.html +++ b/community/lms/widgets/ChapterTeaser.html @@ -7,9 +7,17 @@
{% for lesson in chapter.get_lessons() %}
- {{ lesson.title }} + {% if show_link or lesson.include_in_preview %} + {{ lesson.title }} + {% else %} +
+ + {{ lesson.title }} + + +
+ {% endif %} {% if show_progress and not course.is_mentor(frappe.session.user) and lesson.get_progress() %} {{ lesson.get_progress() }} {% endif %} @@ -18,36 +26,3 @@
- - diff --git a/community/lms/widgets/Quiz.html b/community/lms/widgets/Quiz.html deleted file mode 100644 index 683b0b51..00000000 --- a/community/lms/widgets/Quiz.html +++ /dev/null @@ -1,67 +0,0 @@ -

{{ quiz.title }}

-
- {% for question in quiz.questions %} -
-

{{ loop.index }}. {{ question.question }}

- {% set options = question.options.split(",") %} - {% for option in options %} -
- - {{ option }} -
- {% endfor %} -
- {% endfor %} - - -

-
-
- diff --git a/community/plugins.py b/community/plugins.py index 58fb2765..76cfd4d0 100644 --- a/community/plugins.py +++ b/community/plugins.py @@ -14,6 +14,8 @@ The PageExtension is used to load additinal stylesheets and scripts to be loaded in a webpage. """ +import frappe + class PageExtension: """PageExtension is a plugin to inject custom styles and scripts into a web page. @@ -64,3 +66,24 @@ class ProfileTab: Every subclass must implement this. """ raise NotImplementedError() + +def quiz_renderer(quiz_name): + quiz = frappe.get_doc("LMS Quiz", quiz_name) + context = dict(quiz=quiz) + return frappe.render_template("templates/quiz.html", context) + +def exercise_renderer(argument): + exercise = frappe.get_doc("Exercise", argument) + context = dict(exercise=exercise) + return frappe.render_template("templates/exercise.html", context) + +def youtube_video_renderer(video_id): + return f""" + + """ diff --git a/community/public/css/style.less b/community/public/css/style.less index b74cd666..3de921c9 100644 --- a/community/public/css/style.less +++ b/community/public/css/style.less @@ -76,11 +76,6 @@ h2 { text-decoration: none } -.no-preview:hover { - cursor: pointer; - color: #2490ef; -} - section { padding: 60px 0px; } diff --git a/community/templates/exercise.html b/community/templates/exercise.html new file mode 100644 index 00000000..fca923b7 --- /dev/null +++ b/community/templates/exercise.html @@ -0,0 +1,10 @@ +
+

Exercise {{exercise.index_label}}: {{ exercise.title }}

+
{{frappe.utils.md_to_html(exercise.description)}}
+ + {% set submission = exercise.get_user_submission() %} + +
{{ submission.solution if submission else exercise.code }}
+
diff --git a/community/templates/quiz.html b/community/templates/quiz.html new file mode 100644 index 00000000..3e5de49e --- /dev/null +++ b/community/templates/quiz.html @@ -0,0 +1,30 @@ +{% set last_submission = quiz.get_last_submission_details() %} +{% if last_submission %} +
+
Last Submitted On: {{ frappe.utils.pretty_date(last_submission.creation) }}
+
Last Submission Score: {{ last_submission.score }}
+
+{% endif %} +

{{ quiz.title }}

+
+ {% for question in quiz.questions %} +
+

{{ loop.index }}. {{ question.question }}

+ {% set options = [question.option_1, question.option_2, question.option_3, question.option_4] %} + {% for option in options %} + {% if option %} +
+ + {{ option }} +
+ {% endif %} + {% endfor %} +
+ {% endfor %} + + +

+
+
diff --git a/community/www/batch/home.html b/community/www/batch/home.html index d53888d4..e7542071 100644 --- a/community/www/batch/home.html +++ b/community/www/batch/home.html @@ -11,7 +11,7 @@
{{ widgets.BatchTabs(course=course, membership=membership) }}
- {{ widgets.CourseOutline(course=course, batch=batch, show_link=True, show_progress=True) }} + {{ widgets.CourseOutline(course=course, batch=batch, show_link=membership, show_progress=True) }}
{% if batch %} diff --git a/community/www/batch/learn.html b/community/www/batch/learn.html index 126ee487..a9c08b02 100644 --- a/community/www/batch/learn.html +++ b/community/www/batch/learn.html @@ -36,8 +36,9 @@ Checkout Course Details.
{% endif %} - + {% if membership %} {{ pagination(prev_chap, prev_url, next_chap, next_url) }} + {% endif %} {% endblock %} diff --git a/community/www/batch/learn.js b/community/www/batch/learn.js index e15c5c5c..69699ac4 100644 --- a/community/www/batch/learn.js +++ b/community/www/batch/learn.js @@ -1,4 +1,6 @@ frappe.ready(() => { + + /* Save Lesson Progress */ if ($(".title").attr("data-membership") && !$(".title").hasClass("is_mentor")) { frappe.call({ method: "community.lms.doctype.lesson.lesson.save_progress", @@ -8,10 +10,60 @@ frappe.ready(() => { } }) } + + /* Save Current Lesson */ if ($(".title").attr("data-membership")) { frappe.call("community.lms.api.save_current_lesson", { course_name: $(".title").attr("data-course"), lesson_name: $(".title").attr("data-lesson") }) } + + /* Submit Quiz */ + $("#submit-quiz").click((e) => { + e.preventDefault(); + console.log("click") + var result = []; + $('.question').each((i, element) => { + var options = $(element).find(".option"); + var answers = []; + options.filter((i, op) => $(op).prop("checked")).each((i, elem) => answers.push(decodeURIComponent(elem.value))); + result.push({ + "question": element.dataset.question, + "answer": answers + }); + }); + frappe.call({ + method: "community.lms.doctype.lms_quiz.lms_quiz.submit", + args: { + quiz: $("#title").text(), + result: result + }, + callback: (data) => { + $("#submit-quiz").addClass("hide"); + $("#try-again").removeClass("hide"); + $(":input[type='checkbox']").prop("disabled", true); + $(":input[type='radio']").prop("disabled", true); + if (data.message == result.length) { + $(".success-message").text("Congratulations, you cleared the quiz!"); + } + else { + $(".success-message").text("Some of your answers weren't correct. You can give it another shot."); + } + $(".score").text(`Score: ${data.message}/${result.length}`); + } + }) + }) + + /* Try the quiz again */ + $("#try-again").click((e) => { + e.preventDefault(); + $(":input[type='checkbox']").prop("disabled", false); + $(":input[type='radio']").prop("disabled", false); + $("#quiz-form").trigger("reset"); + $(".success-message").text(""); + $(".score").text(""); + $("#submit-quiz").removeClass("hide"); + $("#try-again").addClass("hide"); + }) }) diff --git a/community/www/batch/utils.py b/community/www/batch/utils.py index 23060680..ea8845c7 100644 --- a/community/www/batch/utils.py +++ b/community/www/batch/utils.py @@ -27,7 +27,7 @@ def get_common_context(context): context.members = course.get_mentors(membership.batch) + course.get_students(membership.batch) context.member_count = len(context.members) - context.course.query_parameter = "?batch=" + membership.batch if membership and membership.batch else "" + context.course.query_parameter = "?batch=" + membership.batch if membership and membership.batch else " " context.livecode_url = get_livecode_url() def get_livecode_url(): diff --git a/community/www/courses/course.html b/community/www/courses/course.html index 7de4c538..7947fd5f 100644 --- a/community/www/courses/course.html +++ b/community/www/courses/course.html @@ -4,6 +4,7 @@ {% block head_include %} + {% endblock %} {% block content %} @@ -30,7 +31,7 @@ {{ CourseDescription(course) }} {{ widgets.InstructorSection(instructor=course.get_instructor()) }} {{ BatchSection(course) }} - {{ widgets.CourseOutline(course=course, show_link=False) }} + {{ widgets.CourseOutline(course=course, show_link=membership) }} diff --git a/community/www/courses/course.py b/community/www/courses/course.py index 3bc2f50f..7f5c5fab 100644 --- a/community/www/courses/course.py +++ b/community/www/courses/course.py @@ -16,8 +16,9 @@ def get_context(context): raise frappe.Redirect context.course = course - if not course.is_mentor(frappe.session.user): - batch = course.get_membership(frappe.session.user) - if batch: - frappe.local.flags.redirect_location = f"/courses/{course.name}/learn" - raise frappe.Redirect + membership = course.get_membership(frappe.session.user) + context.course.query_parameter = "?batch=" + membership.batch if membership and membership.batch else "" + context.membership = membership + if not course.is_mentor(frappe.session.user) and membership: + frappe.local.flags.redirect_location = f"/courses/{course.name}/learn" + raise frappe.Redirect