From 28f9fc3fa8b6ad7866c7ef72f13883af7d6ab7e7 Mon Sep 17 00:00:00 2001 From: adityacp Date: Wed, 9 Sep 2020 17:07:21 +0530 Subject: Show the toc quiz on the student dashboard --- yaksh/forms.py | 2 +- yaksh/models.py | 13 ++- yaksh/static/yaksh/js/show_toc.js | 123 ++++++++++++++++++++++++++ yaksh/templates/base.html | 5 +- yaksh/templates/yaksh/show_lesson_quiz.html | 131 ++++++++++++++++++++++++++++ yaksh/templates/yaksh/show_video.html | 88 ++++++++++--------- yaksh/urls.py | 4 + yaksh/views.py | 51 +++++++++-- 8 files changed, 359 insertions(+), 58 deletions(-) create mode 100644 yaksh/static/yaksh/js/show_toc.js create mode 100644 yaksh/templates/yaksh/show_lesson_quiz.html (limited to 'yaksh') diff --git a/yaksh/forms.py b/yaksh/forms.py index ba8b7d5..440a535 100644 --- a/yaksh/forms.py +++ b/yaksh/forms.py @@ -704,7 +704,7 @@ class VideoQuizForm(forms.ModelForm): {'class': form_input_class, 'placeholder': 'Points'} ) self.fields['type'].widget.attrs.update( - {'class': form_input_class} + {'class': form_input_class, 'readonly': True} ) self.fields['type'].initial = question_type self.fields['description'].widget.attrs.update( diff --git a/yaksh/models.py b/yaksh/models.py index 9ba4afd..851e5c6 100644 --- a/yaksh/models.py +++ b/yaksh/models.py @@ -2762,9 +2762,9 @@ class TableOfContents(models.Model): def get_toc_text(self): if self.content == 1: - content_name = Topic.objects.get(id=self.object_id).name + content_name = self.content_object.name else: - content_name = Question.objects.get(id=self.object_id).summary + content_name = self.content_object.summary return content_name def __str__(self): @@ -2779,6 +2779,15 @@ class Topic(models.Model): return f"{self.name}" +class VideoQuizAnswer(models.Model): + toc = models.ForeignKey(TableOfContents, on_delete=models.CASCADE) + student = models.ForeignKey(User, on_delete=models.CASCADE) + answer = models.ForeignKey(Answer, on_delete=models.CASCADE) + + def __str__(self): + return f"Lesson answer of {self.toc} by {self.user.get_full_name()}" + + class MicroManager(models.Model): manager = models.ForeignKey(User, on_delete=models.CASCADE, related_name='micromanaging', null=True) diff --git a/yaksh/static/yaksh/js/show_toc.js b/yaksh/static/yaksh/js/show_toc.js new file mode 100644 index 0000000..121d9e3 --- /dev/null +++ b/yaksh/static/yaksh/js/show_toc.js @@ -0,0 +1,123 @@ +$(document).ready(function() { + $('#sidebarCollapse').on('click', function () { + $('#sidebar').toggleClass('active'); + }); + player = new Plyr('#player'); + var totalSeconds; + store_video_time(contents_by_time); + var time_arr_length = video_time.length; + player.on('timeupdate', event => { + if (time_arr_length > 0 && player.currentTime >= video_time[loc]) { + var content = contents_by_time[loc]; + loc += 1; + if(content.content != 1) { + player.pause(); + url = $("#toc_"+content.id).val(); + ajax_call(url, "GET"); + } + } + }); +}); + +function store_video_time(contents) { + for (var j = 0; j < contents.length; j++) + video_time.push(get_time_in_seconds(contents[j].time)); +} + +function get_time_in_seconds(time) { + var time = time.split(":"); + var hh = parseInt(time[0]); + var mm = parseInt(time[1]); + var ss = parseInt(time[2]); + return hh * 3600 + mm * 60 + ss; +} + +function lock_screen() { + document.getElementById("ontop").style.display = "block"; +} + +function unlock_screen() { + document.getElementById("ontop").style.display = "none"; +} + +function show_error(error) { + var err_msg = ""; + Object.keys(err).forEach(function(key) { + var value = err[key]; + err_msg = err_msg + key + " : " + value[0].message + "\n"; + }); + alert(err_msg); +} + +function show_question(data) { + $("#dialog").html(data); + $("#dialog").dialog({ + width: 600, + height: 500, + }); + $("#submit-quiz-form").submit(function(e) { + e.preventDefault(); + lock_screen(); + var csrf = document.getElementById("submit-quiz-form").elements[0].value; + ajax_call($(this).attr("action"), $(this).attr("method"), $(this).serialize(), csrf); + }); +} + +function select_toc(element) { + var toc_id = element.getAttribute("data-toc"); + var toc_time = $("#toc_time_"+toc_id).val(); + player.currentTime = get_time_in_seconds(toc_time); + url = $("#toc_"+toc_id).val(); + ajax_call(url, "GET"); +} + +function csrfSafeMethod(method) { + // these HTTP methods do not require CSRF protection + return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method)); +} + +function ajax_call(url, method, data, csrf) { + lock_screen(); + $.ajax({ + url: url, + timeout: 15000, + method: method, + data: data, + beforeSend: function(xhr, settings) { + if (!csrfSafeMethod(settings.type) && !this.crossDomain) { + xhr.setRequestHeader("X-CSRFToken", csrf); + } + }, + success: function(msg) { + unlock_screen(); + if (msg.data) { + show_question(msg.data); + } else { + $("#dialog").dialog("close"); + } + if(msg.message) alert(msg.message); + }, + error: function(xhr, data) { + unlock_screen(); + switch(xhr.status) { + case 400: { + err = JSON.parse(xhr.responseJSON.message); + show_error(err); + break; + } + case 500: { + alert('500 status code! server error'); + break; + } + case 404: { + alert('404 status code! server error'); + break; + } + default: { + alert('Unable to perform action. Please try again'); + break; + } + } + } + }); +} \ No newline at end of file diff --git a/yaksh/templates/base.html b/yaksh/templates/base.html index 7ce653d..53edbee 100644 --- a/yaksh/templates/base.html +++ b/yaksh/templates/base.html @@ -55,9 +55,8 @@
Checking... -
- - + + {% block nav %} {% endblock %} diff --git a/yaksh/templates/yaksh/show_lesson_quiz.html b/yaksh/templates/yaksh/show_lesson_quiz.html new file mode 100644 index 0000000..2d5184e --- /dev/null +++ b/yaksh/templates/yaksh/show_lesson_quiz.html @@ -0,0 +1,131 @@ +{% load custom_filters %} + +
+ {% csrf_token %} +
+
+
+
+

{{ question.summary }}

+
+
+ {% if question.language == "other" %} + Topic: {{question.topic}} + {% else %} + Language: {{question.language}} + {% endif %} + {% if question.type == "mcq" %} + Type: SINGLE CORRECT CHOICE + {% elif question.type == "mcc" %} + Type: MULTIPLE CORRECT CHOICES + {% elif question.type == "integer" %} + Type: FILL IN THE BLANKS WITH INTEGER ANSWER + {% elif question.type == "string" %} + Type: FILL IN THE BLANKS WITH STRING ANSWER + {% if testcase.string_check == "lower" %} +
(CASE INSENSITIVE) + {% else %} +
(CASE SENSITIVE) + {% endif %} + {% elif question.type == "float" %} + Type: FILL IN THE BLANKS WITH FLOAT ANSWER + {% elif question.type == "arrange" %} + Type: ARRANGE THE OPTIONS IN CORRECT ORDER + {% endif %} + + Marks: {{ question.points }} + +
+
+
+
+
+ {{ question.description|safe }} +
+
+ {% if question.type == "mcq" %} + + {% for test_case in test_cases %} + {% if last_attempt and last_attempt|to_int == test_case.id %} + + {{ test_case.options|safe }}
+ {% else %} + + {{ test_case.options|safe }}
+ {% endif %} + {% endfor %} + {% endif %} + + {% if question.type == "integer" %} + + Enter Integer:
+ +

+ {% endif %} + + {% if question.type == "string" %} + + Enter Text:
+ +

+ {% endif %} + + {% if question.type == "float" %} + + Enter Decimal Value :
+ +

+ {% endif %} + + {% if question.type == "mcc" %} + + {% for test_case in test_cases %} + {% if last_attempt and test_case.id|safe in last_attempt|safe %} + + {{ test_case.options| safe }} +
+ {% else %} + + {{ test_case.options| safe }} +
+ {% endif %} + {% endfor %} + {% endif %} + + {% if question.type == "arrange" %} + + {% if last_attempt %} + {% get_answer_for_arrange_options last_attempt question as test_cases %} + {% endif %} + +
+
    + {% for test_case in test_cases %} +
  1. + {{test_case.options| safe }}
  2. {% endfor %} +
+
+ + {% endif %} + {% if question.type == "mcq" or question.type == "mcc" or question.type == "integer" or question.type == "float" or question.type == "string" %} +
+ {% elif question.type == "arrange" %} +
+ {% endif %} +
+
+
\ No newline at end of file diff --git a/yaksh/templates/yaksh/show_video.html b/yaksh/templates/yaksh/show_video.html index 4c54518..8f8bbb2 100644 --- a/yaksh/templates/yaksh/show_video.html +++ b/yaksh/templates/yaksh/show_video.html @@ -4,11 +4,22 @@ {% block title %} {{ learning_module.name }} {% endblock %} {% block script %} - + + + {% endblock %} +{% block css %} + +{% endblock %} {% block main %}
@@ -143,10 +154,6 @@
{% endif %} {% endwith %} -
- - Next  - {% endif %}
@@ -164,14 +171,17 @@ {% with content.get_toc_text as toc_name %} - {{ toc_name }} + {{ toc_name }} {{content.get_content_display}} - + {{content.time}} + + + {% endwith %} {% empty %} @@ -185,48 +195,40 @@
-
-

Lesson Description

-
-
- {{lesson.html_data|safe}} -
-
- {% if not lesson.video_path %} - - Next  - -
- {% endif %} -
- {% with lesson.get_files as lesson_files %} - {% if lesson_files %} -
-
- Files for this lesson -
-
- {% for f in lesson_files %} - - {{forloop.counter}}.{{ f.file.name|file_title }} - - {% endfor %} +
+ + Next  + +
+

Lesson Description

+
+
+ {{lesson.html_data|safe}} +
+
+ {% with lesson.get_files as lesson_files %} + {% if lesson_files %} +
+
+ Files for this lesson +
+
+ {% for f in lesson_files %} + + {{forloop.counter}}.{{ f.file.name|file_title }} + + {% endfor %} +
-
- {% endif %} - {% endwith %} + {% endif %} + {% endwith %} +
{% endif %}
- +
{% endblock %} diff --git a/yaksh/urls.py b/yaksh/urls.py index e4f81e1..2b9a04f 100644 --- a/yaksh/urls.py +++ b/yaksh/urls.py @@ -259,4 +259,8 @@ urlpatterns = [ name='edit_marker_quiz'), path('manage/remove/lesson/toc//', views.delete_toc, name='delete_toc'), + path('get/marker/quiz//', views.get_marker_quiz, + name='get_marker_quiz'), + path('submit/marker/quiz//', + views.submit_marker_quiz, name='submit_marker_quiz'), ] diff --git a/yaksh/views.py b/yaksh/views.py index 652e08c..6f8aa2f 100644 --- a/yaksh/views.py +++ b/yaksh/views.py @@ -38,11 +38,7 @@ from yaksh.models import ( StdIOBasedTestCase, StringTestCase, TestCase, User, get_model_class, FIXTURES_DIR_PATH, MOD_GROUP_NAME, Lesson, LessonFile, LearningUnit, LearningModule, CourseStatus, question_types, Post, Comment, -<<<<<<< HEAD - Topic, TableOfContents -======= - MicroManager ->>>>>>> 23bf46ac2e262ceb373388196962a0bec048c6cb + Topic, TableOfContents, MicroManager ) from yaksh.forms import ( UserRegisterForm, UserLoginForm, QuizForm, QuestionForm, @@ -2759,6 +2755,9 @@ def show_lesson(request, lesson_id, module_id, course_id): _update_unit_status(course_id, user, learn_unit) toc = TableOfContents.objects.filter( course_id=course_id, lesson_id=lesson_id + ).order_by("time") + contents_by_time = json.dumps( + list(toc.values("id", "content", "time")) ) all_modules = course.get_learning_modules() if learn_unit.has_prerequisite(): @@ -2768,7 +2767,8 @@ def show_lesson(request, lesson_id, module_id, course_id): context = {'lesson': learn_unit.lesson, 'user': user, 'course': course, 'state': "lesson", "all_modules": all_modules, 'learning_units': learning_units, "current_unit": learn_unit, - 'learning_module': learn_module, 'toc': toc} + 'learning_module': learn_module, 'toc': toc, + 'contents_by_time': contents_by_time} return my_render_to_response(request, 'yaksh/show_video.html', context) @@ -3504,7 +3504,6 @@ def hide_comment(request, course_id, uuid): @login_required @email_verified -<<<<<<< HEAD def add_marker(request, course_id, lesson_id): user = request.user course = get_object_or_404(Course, pk=course_id) @@ -3645,7 +3644,7 @@ def add_topic(request, content_type, course_id, lesson_id, toc_id=None, toc.save() status_code = 200 context['success'] = True - context['message'] = 'Added topic successfully' + context['message'] = 'Saved topic successfully' else: status_code = 400 context['success'] = False @@ -3709,7 +3708,7 @@ def add_marker_quiz(request, content_type, course_id, lesson_id, toc.save() status_code = 200 context['success'] = True - context['message'] = 'Added question successfully' + context['message'] = 'Saved question successfully' context['content_type'] = content_type else: status_code = 400 @@ -3802,3 +3801,37 @@ def extend_time(request, paper_id): messages.info(request, msg) return my_redirect('/exam/manage/monitor/{0}/{1}/'.format( anspaper.question_paper.quiz.id, course.id)) + + +@login_required +@email_verified +def get_marker_quiz(request, course_id, toc_id): + user = request.user + course = get_object_or_404(Course, pk=course_id) + if not course.is_student(user): + raise Http404("You are not allowed to view this page") + toc = get_object_or_404(TableOfContents, pk=toc_id) + question = toc.content_object + template_context = { + "question": question, "course_id": course_id, "toc": toc, + "test_cases": question.get_test_cases() + } + data = loader.render_to_string( + "yaksh/show_lesson_quiz.html", context=template_context, + request=request + ) + context = {"data": data, "success": True} + return JsonResponse(context) + + +@login_required +@email_verified +def submit_marker_quiz(request, course_id, toc_id): + user = request.user + course = get_object_or_404(Course, pk=course_id) + if not course.is_student(user): + raise Http404("You are not allowed to view this page") + toc = get_object_or_404(TableOfContents, pk=toc_id) + print(request.POST) + context = {"success": True} + return JsonResponse(context) -- cgit