From d54b62c2803f0f0edb45348f47d6a541ca09e022 Mon Sep 17 00:00:00 2001 From: adityacp Date: Wed, 26 Aug 2020 20:29:03 +0530 Subject: First cut for in video quizzes --- yaksh/views.py | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 89 insertions(+), 8 deletions(-) (limited to 'yaksh/views.py') diff --git a/yaksh/views.py b/yaksh/views.py index 3adb536..495dbe2 100644 --- a/yaksh/views.py +++ b/yaksh/views.py @@ -3,7 +3,7 @@ import csv from django.http import HttpResponse, JsonResponse, HttpResponseRedirect from django.contrib.auth import login, logout, authenticate from django.shortcuts import render, get_object_or_404, redirect -from django.template import Context, Template +from django.template import Context, Template, loader from django.http import Http404 from django.db.models import Max, Q, F from django.db import models @@ -44,7 +44,7 @@ from yaksh.forms import ( QuestionFilterForm, CourseForm, ProfileForm, UploadFileForm, FileForm, QuestionPaperForm, LessonForm, LessonFileForm, LearningModuleForm, ExerciseForm, TestcaseForm, - SearchFilterForm, PostForm, CommentForm + SearchFilterForm, PostForm, CommentForm, TopicForm, VideoQuizForm ) from yaksh.settings import SERVER_POOL_PORT, SERVER_HOST_NAME from .settings import URL_ROOT @@ -2576,6 +2576,8 @@ def edit_lesson(request, course_id=None, module_id=None, lesson_id=None): raise Http404('This Lesson does not belong to you') context = {} + lesson_form = LessonForm(instance=lesson) + lesson_files_form = LessonFileForm() if request.method == "POST": if "Save" in request.POST: lesson_form = LessonForm(request.POST, request.FILES, @@ -2615,10 +2617,6 @@ def edit_lesson(request, course_id=None, module_id=None, lesson_id=None): reverse("yaksh:edit_lesson", args=[course_id, module_id, lesson.id]) ) - else: - context['lesson_form'] = lesson_form - context['error'] = lesson_form["video_file"].errors - context['lesson_file_form'] = lesson_file_form if 'Delete' in request.POST: remove_files_id = request.POST.getlist('delete_files') @@ -2635,8 +2633,6 @@ def edit_lesson(request, course_id=None, module_id=None, lesson_id=None): ) lesson_files = LessonFile.objects.filter(lesson=lesson) - lesson_files_form = LessonFileForm() - lesson_form = LessonForm(instance=lesson) context['lesson_form'] = lesson_form context['lesson_file_form'] = lesson_files_form context['lesson_files'] = lesson_files @@ -3420,3 +3416,88 @@ def hide_comment(request, course_id, uuid): comment.active = False comment.save() return redirect('yaksh:post_comments', course_id, post_uid) + + +@login_required +@email_verified +def add_marker(request, course_id, lesson_id): + user = request.user + course = get_object_or_404(Course, pk=course_id) + if (not is_moderator(user) or + not course.is_creator(user) or not course.is_creator(user)): + raise Http404("You are not allowed to view this page") + data = json.loads(request.body.decode("utf-8")) + content_type = data[-2].get("value") + print(content_type) + if content_type == '1': + form = TopicForm() + template_name = 'yaksh/add_topic.html' + status = 1 + formset = None + tc_class = None + else: + try: + question_type = data[-1].get('value') + except IndexError: + question_type = "mcq" + form = VideoQuizForm(question_type=question_type) + formset, tc_class = get_tc_formset(question_type) + template_name = 'yaksh/add_video_quiz.html' + status = 2 + context = {'form': form, 'course_id': course.id, 'lesson_id': lesson_id, + 'formset': formset, 'tc_class': tc_class} + data = loader.render_to_string( + template_name, context=context, request=request + ) + return JsonResponse( + {'success': True, 'data': data, 'content_type': content_type, + 'status': status} + ) + +def get_tc_formset(question_type): + tc, tc_class = McqTestCase, 'mcqtestcase' + if question_type == 'mcq' or question_type == 'mcc': + tc, tc_class = McqTestCase, 'mcqtestcase' + elif question_type == 'integer': + tc, tc_class = IntegerTestCase, 'integertestcase' + elif question_type == 'float': + tc, tc_class = FloatTestCase, 'floattestcase' + elif question_type == 'string': + tc, tc_class = StringTestCase, 'stringtestcase' + TestcaseFormset = inlineformset_factory( + Question, tc, form=TestcaseForm, extra=1, fields="__all__", + ) + formset = TestcaseFormset(initial=[{'type': tc_class}]) + return formset, tc_class + + +@login_required +@email_verified +def add_topic(request, course_id, lesson_id, topic_id=None): + user = request.user + course = get_object_or_404(Course, pk=course_id) + if (not is_moderator(user) or + not course.is_creator(user) or not course.is_creator(user)): + raise Http404("You are not allowed to view this page") + print(request.method) + data = json.loads(request.body.decode("utf-8")) + print(data) + return JsonResponse( + {'success': True, 'data': data, 'message': 'Added successfully'} + ) + + +@login_required +@email_verified +def add_marker_quiz(request, course_id, lesson_id, question_id=None): + user = request.user + course = get_object_or_404(Course, pk=course_id) + if (not is_moderator(user) or + not course.is_creator(user) or not course.is_creator(user)): + raise Http404("You are not allowed to view this page") + print(request.method) + data = json.loads(request.body.decode("utf-8")) + print(data) + return JsonResponse( + {'success': True, 'data': data, 'message': 'Added successfully'} + ) -- cgit From 23c6caab733f5bba6458a07a6666a0580ee2e6a9 Mon Sep 17 00:00:00 2001 From: adityacp Date: Thu, 3 Sep 2020 18:18:18 +0530 Subject: Change views, forms, models, urls - Disable the question type in video question form - Change urls to add graded quiz, exercise, poll type question - Save the topic and question in table of contents - Rename lesson attribute in TableOfContents model --- yaksh/views.py | 121 +++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 97 insertions(+), 24 deletions(-) (limited to 'yaksh/views.py') diff --git a/yaksh/views.py b/yaksh/views.py index 668a88c..db46d90 100644 --- a/yaksh/views.py +++ b/yaksh/views.py @@ -37,7 +37,8 @@ from yaksh.models import ( QuestionPaper, QuestionSet, Quiz, Question, StandardTestCase, StdIOBasedTestCase, StringTestCase, TestCase, User, get_model_class, FIXTURES_DIR_PATH, MOD_GROUP_NAME, Lesson, LessonFile, - LearningUnit, LearningModule, CourseStatus, question_types, Post, Comment + LearningUnit, LearningModule, CourseStatus, question_types, Post, Comment, + Topic, TableOfContents ) from yaksh.forms import ( UserRegisterForm, UserLoginForm, QuizForm, QuestionForm, @@ -2634,6 +2635,14 @@ def edit_lesson(request, course_id=None, module_id=None, lesson_id=None): request, "Please select atleast one file to delete" ) + contents = TableOfContents.objects.filter( + course_id=course_id, lesson_id=lesson_id + ) + data = loader.render_to_string( + "yaksh/show_toc.html", context={'contents': contents}, + request=request + ) + context['toc'] = data lesson_files = LessonFile.objects.filter(lesson=lesson) context['lesson_form'] = lesson_form context['lesson_file_form'] = lesson_files_form @@ -3428,9 +3437,8 @@ def add_marker(request, course_id, lesson_id): if (not is_moderator(user) or not course.is_creator(user) or not course.is_creator(user)): raise Http404("You are not allowed to view this page") - data = json.loads(request.body.decode("utf-8")) - content_type = data[-2].get("value") - print(content_type) + content_type = request.POST.get("content") + question_type = request.POST.get("type") if content_type == '1': form = TopicForm() template_name = 'yaksh/add_topic.html' @@ -3438,16 +3446,15 @@ def add_marker(request, course_id, lesson_id): formset = None tc_class = None else: - try: - question_type = data[-1].get('value') - except IndexError: + if not question_type: question_type = "mcq" form = VideoQuizForm(question_type=question_type) formset, tc_class = get_tc_formset(question_type) template_name = 'yaksh/add_video_quiz.html' status = 2 context = {'form': form, 'course_id': course.id, 'lesson_id': lesson_id, - 'formset': formset, 'tc_class': tc_class} + 'formset': formset, 'tc_class': tc_class, + 'content_type': content_type} data = loader.render_to_string( template_name, context=context, request=request ) @@ -3456,7 +3463,8 @@ def add_marker(request, course_id, lesson_id): 'status': status} ) -def get_tc_formset(question_type): + +def get_tc_formset(question_type, post=None, question=None): tc, tc_class = McqTestCase, 'mcqtestcase' if question_type == 'mcq' or question_type == 'mcc': tc, tc_class = McqTestCase, 'mcqtestcase' @@ -3469,37 +3477,102 @@ def get_tc_formset(question_type): TestcaseFormset = inlineformset_factory( Question, tc, form=TestcaseForm, extra=1, fields="__all__", ) - formset = TestcaseFormset(initial=[{'type': tc_class}]) + formset = TestcaseFormset( + post, initial=[{'type': tc_class}], instance=question + ) return formset, tc_class @login_required @email_verified -def add_topic(request, course_id, lesson_id, topic_id=None): +def add_topic(request, content_type, course_id, lesson_id, topic_id=None): user = request.user course = get_object_or_404(Course, pk=course_id) if (not is_moderator(user) or not course.is_creator(user) or not course.is_creator(user)): raise Http404("You are not allowed to view this page") - print(request.method) - data = json.loads(request.body.decode("utf-8")) - print(data) - return JsonResponse( - {'success': True, 'data': data, 'message': 'Added successfully'} - ) + if topic_id: + topic = get_object_or_404(Topic, pk=topic_id) + else: + topic = None + context = {} + if request.method == "POST": + form = TopicForm(request.POST, instance=topic) + if form.is_valid(): + form.save() + if not topic: + TableOfContents.objects.create( + content_object=form.instance, course_id=course_id, + lesson_id=lesson_id, content=content_type, + time=request.POST.get("timer") + ) + contents = TableOfContents.objects.filter( + course_id=course_id, lesson_id=lesson_id + ) + data = loader.render_to_string( + "yaksh/show_toc.html", context={'contents': contents}, + request=request + ) + context['toc'] = data + status_code = 200 + context['success'] = True + context['message'] = 'Added topic successfully' + else: + status_code = 400 + context['success'] = False + context['message'] = form.errors.as_json() + return JsonResponse(context, status=status_code) @login_required @email_verified -def add_marker_quiz(request, course_id, lesson_id, question_id=None): +def add_marker_quiz(request, content_type, course_id, lesson_id, + question_id=None): user = request.user course = get_object_or_404(Course, pk=course_id) if (not is_moderator(user) or not course.is_creator(user) or not course.is_creator(user)): raise Http404("You are not allowed to view this page") - print(request.method) - data = json.loads(request.body.decode("utf-8")) - print(data) - return JsonResponse( - {'success': True, 'data': data, 'message': 'Added successfully'} - ) + if question_id: + question = get_object_or_404(Question, pk=question_id) + else: + question = None + context = {} + if request.method == "POST": + qform = VideoQuizForm(request.POST, instance=question) + if qform.is_valid(): + qform.save(commit=False) + qform.instance.user = user + qform.save() + formset, tc_class = get_tc_formset( + qform.instance.type, request.POST, qform.instance + ) + if formset.is_valid(): + formset.save() + if not question: + TableOfContents.objects.create( + content_object=qform.instance, course_id=course_id, + lesson_id=lesson_id, content=content_type, + time=request.POST.get("timer") + ) + contents = TableOfContents.objects.filter( + course_id=course_id, lesson_id=lesson_id + ) + data = loader.render_to_string( + "yaksh/show_toc.html", context={'contents': contents}, + request=request + ) + context['toc'] = data + status_code = 200 + context['success'] = True + context['message'] = 'Added question successfully' + context['content_type'] = content_type + else: + status_code = 400 + context['success'] = False + context['message'] = formset.errors.as_json() + else: + status_code = 400 + context['success'] = False + context['message'] = qform.errors.as_json() + return JsonResponse(context, status=status_code) -- cgit From 7e5608d0853d69358c14f9fb8fbd6465e21b8962 Mon Sep 17 00:00:00 2001 From: adityacp Date: Mon, 7 Sep 2020 12:53:08 +0530 Subject: Add edit and delete table of contents options --- yaksh/views.py | 115 ++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 90 insertions(+), 25 deletions(-) (limited to 'yaksh/views.py') diff --git a/yaksh/views.py b/yaksh/views.py index db46d90..60d72e9 100644 --- a/yaksh/views.py +++ b/yaksh/views.py @@ -2686,6 +2686,9 @@ def show_lesson(request, lesson_id, module_id, course_id): # update course status with current unit _update_unit_status(course_id, user, learn_unit) + toc = TableOfContents.objects.filter( + course_id=course_id, lesson_id=lesson_id + ) all_modules = course.get_learning_modules() if learn_unit.has_prerequisite(): @@ -2695,7 +2698,7 @@ 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} + 'learning_module': learn_module, 'toc': toc} return my_render_to_response(request, 'yaksh/show_video.html', context) @@ -3478,14 +3481,26 @@ def get_tc_formset(question_type, post=None, question=None): Question, tc, form=TestcaseForm, extra=1, fields="__all__", ) formset = TestcaseFormset( - post, initial=[{'type': tc_class}], instance=question + post, initial=[{'type': tc_class}], instance=question ) return formset, tc_class +def get_toc_contents(request, course_id, lesson_id): + contents = TableOfContents.objects.filter( + course_id=course_id, lesson_id=lesson_id + ) + data = loader.render_to_string( + "yaksh/show_toc.html", context={'contents': contents}, + request=request + ) + return data + + @login_required @email_verified -def add_topic(request, content_type, course_id, lesson_id, topic_id=None): +def add_topic(request, content_type, course_id, lesson_id, toc_id=None, + topic_id=None): user = request.user course = get_object_or_404(Course, pk=course_id) if (not is_moderator(user) or @@ -3495,25 +3510,26 @@ def add_topic(request, content_type, course_id, lesson_id, topic_id=None): topic = get_object_or_404(Topic, pk=topic_id) else: topic = None + if toc_id: + toc = get_object_or_404(TableOfContents, pk=toc_id) + else: + toc = None context = {} if request.method == "POST": form = TopicForm(request.POST, instance=topic) if form.is_valid(): form.save() + time = request.POST.get("timer") if not topic: TableOfContents.objects.create( content_object=form.instance, course_id=course_id, lesson_id=lesson_id, content=content_type, - time=request.POST.get("timer") - ) - contents = TableOfContents.objects.filter( - course_id=course_id, lesson_id=lesson_id - ) - data = loader.render_to_string( - "yaksh/show_toc.html", context={'contents': contents}, - request=request + time=time ) - context['toc'] = data + context['toc'] = get_toc_contents(request, course_id, lesson_id) + if toc: + toc.time = time + toc.save() status_code = 200 context['success'] = True context['message'] = 'Added topic successfully' @@ -3521,13 +3537,26 @@ def add_topic(request, content_type, course_id, lesson_id, topic_id=None): status_code = 400 context['success'] = False context['message'] = form.errors.as_json() + else: + form = TopicForm(instance=topic, time=toc.time) + template_context = {'form': form, 'course_id': course.id, + 'lesson_id': lesson_id, 'content_type': content_type, + 'topic_id': topic_id, 'toc_id': toc_id} + data = loader.render_to_string( + "yaksh/add_topic.html", context=template_context, request=request + ) + context['success'] = True + context['data'] = data + context['content_type'] = content_type + context['status'] = 1 + status_code = 200 return JsonResponse(context, status=status_code) @login_required @email_verified def add_marker_quiz(request, content_type, course_id, lesson_id, - question_id=None): + toc_id=None, question_id=None): user = request.user course = get_object_or_404(Course, pk=course_id) if (not is_moderator(user) or @@ -3537,32 +3566,34 @@ def add_marker_quiz(request, content_type, course_id, lesson_id, question = get_object_or_404(Question, pk=question_id) else: question = None + if toc_id: + toc = get_object_or_404(TableOfContents, pk=toc_id) + else: + toc = None context = {} if request.method == "POST": qform = VideoQuizForm(request.POST, instance=question) if qform.is_valid(): - qform.save(commit=False) - qform.instance.user = user + if not question_id: + qform.save(commit=False) + qform.instance.user = user qform.save() formset, tc_class = get_tc_formset( qform.instance.type, request.POST, qform.instance ) if formset.is_valid(): formset.save() + time = request.POST.get("timer") if not question: TableOfContents.objects.create( content_object=qform.instance, course_id=course_id, lesson_id=lesson_id, content=content_type, - time=request.POST.get("timer") + time=time ) - contents = TableOfContents.objects.filter( - course_id=course_id, lesson_id=lesson_id - ) - data = loader.render_to_string( - "yaksh/show_toc.html", context={'contents': contents}, - request=request - ) - context['toc'] = data + context['toc'] = get_toc_contents(request, course_id, lesson_id) + if toc: + toc.time = time + toc.save() status_code = 200 context['success'] = True context['message'] = 'Added question successfully' @@ -3570,9 +3601,43 @@ def add_marker_quiz(request, content_type, course_id, lesson_id, else: status_code = 400 context['success'] = False - context['message'] = formset.errors.as_json() + context['message'] = "Error in saving form" else: status_code = 400 context['success'] = False context['message'] = qform.errors.as_json() + else: + form = VideoQuizForm(instance=question, time=toc.time) + formset, tc_class = get_tc_formset(question.type, question=question) + template_context = { + 'form': form, 'course_id': course.id, 'lesson_id': lesson_id, + 'formset': formset, 'tc_class': tc_class, 'toc_id': toc_id, + 'content_type': content_type, 'question_id': question_id + } + data = loader.render_to_string( + "yaksh/add_video_quiz.html", context=template_context, + request=request + ) + context['success'] = True + context['data'] = data + context['content_type'] = content_type + context['status'] = 2 + status_code = 200 return JsonResponse(context, status=status_code) + + +@login_required +@email_verified +def delete_toc(request, course_id, toc_id): + user = request.user + course = get_object_or_404(Course, pk=course_id) + if (not is_moderator(user) or + not course.is_creator(user) or not course.is_creator(user)): + raise Http404("You are not allowed to view this page") + toc = get_object_or_404(TableOfContents, pk=toc_id) + redirect_url = request.POST.get("redirect_url") + if toc.content == 1: + get_object_or_404(Topic, pk=toc.object_id).delete() + else: + get_object_or_404(Question, id=toc.object_id).delete() + return redirect(redirect_url) -- cgit From 2d1b8eb907c7e142d4e3c76e43707fb9f82d6683 Mon Sep 17 00:00:00 2001 From: adityacp Date: Mon, 7 Sep 2020 13:43:09 +0530 Subject: Show the lesson contents on student interface --- yaksh/views.py | 1 - 1 file changed, 1 deletion(-) (limited to 'yaksh/views.py') diff --git a/yaksh/views.py b/yaksh/views.py index 60d72e9..fffefe8 100644 --- a/yaksh/views.py +++ b/yaksh/views.py @@ -2689,7 +2689,6 @@ def show_lesson(request, lesson_id, module_id, course_id): toc = TableOfContents.objects.filter( course_id=course_id, lesson_id=lesson_id ) - all_modules = course.get_learning_modules() if learn_unit.has_prerequisite(): if not learn_unit.is_prerequisite_complete(user, learn_module, course): -- cgit 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/views.py | 51 ++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 42 insertions(+), 9 deletions(-) (limited to 'yaksh/views.py') 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 From bee8d54d8ae094db5e3c9c04c5e28fb5b2abb1df Mon Sep 17 00:00:00 2001 From: adityacp Date: Thu, 10 Sep 2020 18:40:16 +0530 Subject: Store and evaluate lesson quiz answer --- yaksh/views.py | 51 ++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 48 insertions(+), 3 deletions(-) (limited to 'yaksh/views.py') diff --git a/yaksh/views.py b/yaksh/views.py index 6f8aa2f..ff22a26 100644 --- a/yaksh/views.py +++ b/yaksh/views.py @@ -38,7 +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, - Topic, TableOfContents, MicroManager + Topic, TableOfContents, VideoQuizAnswer, MicroManager ) from yaksh.forms import ( UserRegisterForm, UserLoginForm, QuizForm, QuestionForm, @@ -3832,6 +3832,51 @@ def submit_marker_quiz(request, course_id, toc_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} + current_question = toc.content_object + if current_question.type == 'mcq': + user_answer = request.POST.get('answer') + elif current_question.type == 'integer': + try: + user_answer = int(request.POST.get('answer')) + except ValueError: + msg = "Please enter an Integer Value" + elif current_question.type == 'float': + try: + user_answer = float(request.POST.get('answer')) + except ValueError: + msg = "Please enter a Float Value" + elif current_question.type == 'string': + user_answer = str(request.POST.get('answer')) + elif current_question.type == 'mcc': + user_answer = request.POST.getlist('answer') + elif current_question.type == 'arrange': + user_answer_ids = request.POST.get('answer').split(',') + user_answer = [int(ids) for ids in user_answer_ids] + + def is_valid_answer(user_answer): + success = True + if current_question.type == "mcc" and not user_answer: + success = False + elif not str(user_answer): + success = False + return success + + if is_valid_answer(user_answer): + if not VideoQuizAnswer.objects.filter( + toc_id=toc_id, student_id=user.id).exists(): + answer = Answer.objects.create( + question_id=current_question.id, answer=user_answer, + correct=False, error=json.dumps([]) + ) + lesson_ans = VideoQuizAnswer.objects.create( + toc_id=toc_id, student=user, answer=answer + ) + if toc.content == 2: + lesson_ans.check_answer(user_answer) + msg = "Answer saved successfully" + else: + msg = "You have already submitted the answer" + else: + msg = "Please submit a valid answer" + context = {"success": True, "message": msg} return JsonResponse(context) -- cgit From b1d2b88746fc670d7362f9b4d175d5e570f3ac77 Mon Sep 17 00:00:00 2001 From: adityacp Date: Sat, 12 Sep 2020 11:44:01 +0530 Subject: Mulitple changes - Remove all alerts and add toast messages - Accept user submissions for the lesson quiz and evaluate - Initial lesson statistics --- yaksh/views.py | 62 +++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 46 insertions(+), 16 deletions(-) (limited to 'yaksh/views.py') diff --git a/yaksh/views.py b/yaksh/views.py index ff22a26..c817c51 100644 --- a/yaksh/views.py +++ b/yaksh/views.py @@ -38,7 +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, - Topic, TableOfContents, VideoQuizAnswer, MicroManager + Topic, TableOfContents, LessonQuizAnswer, MicroManager ) from yaksh.forms import ( UserRegisterForm, UserLoginForm, QuizForm, QuestionForm, @@ -3772,6 +3772,7 @@ def delete_toc(request, course_id, toc_id): get_object_or_404(Topic, pk=toc.object_id).delete() else: get_object_or_404(Question, id=toc.object_id).delete() + messages.success(request, "Content deleted successfully") return redirect(redirect_url) @@ -3839,12 +3840,12 @@ def submit_marker_quiz(request, course_id, toc_id): try: user_answer = int(request.POST.get('answer')) except ValueError: - msg = "Please enter an Integer Value" + user_answer = None elif current_question.type == 'float': try: user_answer = float(request.POST.get('answer')) except ValueError: - msg = "Please enter a Float Value" + user_answer = None elif current_question.type == 'string': user_answer = str(request.POST.get('answer')) elif current_question.type == 'mcc': @@ -3853,30 +3854,59 @@ def submit_marker_quiz(request, course_id, toc_id): user_answer_ids = request.POST.get('answer').split(',') user_answer = [int(ids) for ids in user_answer_ids] - def is_valid_answer(user_answer): - success = True - if current_question.type == "mcc" and not user_answer: - success = False - elif not str(user_answer): - success = False - return success + def is_valid_answer(answer): + status = True + if ((current_question.type == "mcc" or + current_question.type == "arrange") and not answer): + status = False + elif answer is None or not str(answer): + status = False + return status if is_valid_answer(user_answer): - if not VideoQuizAnswer.objects.filter( - toc_id=toc_id, student_id=user.id).exists(): + success = True + # check if graded quiz and already attempted + has_attempts = LessonQuizAnswer.objects.filter( + toc_id=toc_id, student_id=user.id).exists() + if ((toc.content == 2 and not has_attempts) or + toc.content == 3 or toc.content == 4): answer = Answer.objects.create( question_id=current_question.id, answer=user_answer, correct=False, error=json.dumps([]) ) - lesson_ans = VideoQuizAnswer.objects.create( + lesson_ans = LessonQuizAnswer.objects.create( toc_id=toc_id, student=user, answer=answer ) - if toc.content == 2: - lesson_ans.check_answer(user_answer) msg = "Answer saved successfully" + # call check answer only for graded quiz and exercise + if toc.content == 3 or toc.content == 2: + result = lesson_ans.check_answer(user_answer) + # if exercise then show custom message + if toc.content == 3: + if result.get("success"): + msg = "You answered the question correctly" + else: + success = False + msg = "You have answered the question incorrectly. "\ + "Please refer the lesson again" else: msg = "You have already submitted the answer" else: + success = False msg = "Please submit a valid answer" - context = {"success": True, "message": msg} + context = {"success": success, "message": msg} return JsonResponse(context) + + +@login_required +@email_verified +def lessson_statistics(request, course_id, lesson_id): + user = request.user + course = get_object_or_404(Course, pk=course_id) + if (not is_moderator(user) or + not course.is_creator(user) or not course.is_creator(user)): + raise Http404("You are not allowed to view this page") + toc = TableOfContents.objects.get_data(course_id, lesson_id) + return render(request, 'yaksh/show_lesson_statistics.html', { + 'data': toc, + }) -- cgit From 98908b86a94da4a2552564e057457c48b46d4ac3 Mon Sep 17 00:00:00 2001 From: adityacp Date: Mon, 14 Sep 2020 16:04:35 +0530 Subject: Show lesson quiz statistics --- yaksh/views.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'yaksh/views.py') diff --git a/yaksh/views.py b/yaksh/views.py index c817c51..ab0f95d 100644 --- a/yaksh/views.py +++ b/yaksh/views.py @@ -3900,13 +3900,19 @@ def submit_marker_quiz(request, course_id, toc_id): @login_required @email_verified -def lessson_statistics(request, course_id, lesson_id): +def lesson_statistics(request, course_id, lesson_id, toc_id=None): user = request.user course = get_object_or_404(Course, pk=course_id) if (not is_moderator(user) or not course.is_creator(user) or not course.is_creator(user)): raise Http404("You are not allowed to view this page") - toc = TableOfContents.objects.get_data(course_id, lesson_id) - return render(request, 'yaksh/show_lesson_statistics.html', { - 'data': toc, - }) + context = {} + data = TableOfContents.objects.get_data(course_id, lesson_id) + context['data'] = data + context['lesson'] = next(iter(data)).lesson + context['course_id'] = course_id + if toc_id: + per_que_data = TableOfContents.objects.get_question_stats(toc_id) + context['per_que_data'] = per_que_data + context['is_que_data'] = True + return render(request, 'yaksh/show_lesson_statistics.html', context) -- cgit From a9a8f286767468a55709215fbe584157f32a7300 Mon Sep 17 00:00:00 2001 From: adityacp Date: Tue, 15 Sep 2020 13:50:24 +0530 Subject: Change multiple sections - Show lesson topic description as per the video time - Fix description preview for module and lesson - Order table of contents by time --- yaksh/views.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'yaksh/views.py') diff --git a/yaksh/views.py b/yaksh/views.py index ab0f95d..e8bc2c6 100644 --- a/yaksh/views.py +++ b/yaksh/views.py @@ -2704,7 +2704,7 @@ def edit_lesson(request, course_id=None, module_id=None, lesson_id=None): contents = TableOfContents.objects.filter( course_id=course_id, lesson_id=lesson_id - ) + ).order_by("time") data = loader.render_to_string( "yaksh/show_toc.html", context={'contents': contents}, request=request @@ -3559,7 +3559,7 @@ def get_tc_formset(question_type, post=None, question=None): def get_toc_contents(request, course_id, lesson_id): contents = TableOfContents.objects.filter( course_id=course_id, lesson_id=lesson_id - ) + ).order_by("time") data = loader.render_to_string( "yaksh/show_toc.html", context={'contents': contents}, request=request -- cgit From f02cd58ea21e08c9a7e8120fd5ced3263cf904f6 Mon Sep 17 00:00:00 2001 From: adityacp Date: Mon, 21 Sep 2020 19:12:45 +0530 Subject: Add pagination in the lesson statistics --- yaksh/views.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'yaksh/views.py') diff --git a/yaksh/views.py b/yaksh/views.py index 2be8734..d909627 100644 --- a/yaksh/views.py +++ b/yaksh/views.py @@ -3906,12 +3906,17 @@ def lesson_statistics(request, course_id, lesson_id, toc_id=None): not course.is_creator(user) or not course.is_creator(user)): raise Http404("You are not allowed to view this page") context = {} + lesson = get_object_or_404(Lesson, id=lesson_id) data = TableOfContents.objects.get_data(course_id, lesson_id) context['data'] = data - context['lesson'] = next(iter(data)).lesson + context['lesson'] = lesson context['course_id'] = course_id if toc_id: per_que_data = TableOfContents.objects.get_question_stats(toc_id) - context['per_que_data'] = per_que_data + paginator = Paginator(per_que_data[1], 50) + context['question'] = per_que_data[0] + page = request.GET.get('page') + per_que_data = paginator.get_page(page) context['is_que_data'] = True + context['objects'] = per_que_data return render(request, 'yaksh/show_lesson_statistics.html', context) -- cgit From 7589f9838ac5080a5f2fb5f9c92522bc722ab80b Mon Sep 17 00:00:00 2001 From: adityacp Date: Wed, 23 Sep 2020 18:01:04 +0530 Subject: Add more tests --- yaksh/views.py | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'yaksh/views.py') diff --git a/yaksh/views.py b/yaksh/views.py index d909627..4c3b4a6 100644 --- a/yaksh/views.py +++ b/yaksh/views.py @@ -3710,9 +3710,10 @@ def add_marker_quiz(request, content_type, course_id, lesson_id, context['message'] = 'Saved question successfully' context['content_type'] = content_type else: - status_code = 400 + status_code = 200 context['success'] = False - context['message'] = "Error in saving form" + context['message'] = "Error in saving."\ + " Please check the question test cases" else: status_code = 400 context['success'] = False @@ -3880,14 +3881,14 @@ def submit_marker_quiz(request, course_id, toc_id): # call check answer only for graded quiz and exercise if toc.content == 3 or toc.content == 2: result = lesson_ans.check_answer(user_answer) - # if exercise then show custom message - if toc.content == 3: - if result.get("success"): - msg = "You answered the question correctly" - else: - success = False - msg = "You have answered the question incorrectly. "\ - "Please refer the lesson again" + # if exercise then show custom message + if toc.content == 3: + if result.get("success"): + msg = "You answered the question correctly" + else: + success = False + msg = "You have answered the question incorrectly. "\ + "Please refer the lesson again" else: msg = "You have already submitted the answer" else: -- cgit From 4ab3353b4a6dc28764c8536e6b089f7feb65f015 Mon Sep 17 00:00:00 2001 From: adityacp Date: Fri, 25 Sep 2020 13:45:03 +0530 Subject: Add condition to check for course teacher --- yaksh/views.py | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) (limited to 'yaksh/views.py') diff --git a/yaksh/views.py b/yaksh/views.py index b6f935b..be19d19 100644 --- a/yaksh/views.py +++ b/yaksh/views.py @@ -3505,10 +3505,11 @@ def hide_comment(request, course_id, uuid): @email_verified def add_marker(request, course_id, lesson_id): user = request.user + if not is_moderator(user): + raise Http404('You are not allowed to view this page!') course = get_object_or_404(Course, pk=course_id) - if (not is_moderator(user) or - not course.is_creator(user) or not course.is_creator(user)): - raise Http404("You are not allowed to view this page") + if not course.is_creator(user) and not course.is_teacher(user): + raise Http404('This course does not belong to you') content_type = request.POST.get("content") question_type = request.POST.get("type") if content_type == '1': @@ -3612,10 +3613,11 @@ def allow_special_attempt(request, user_id, course_id, quiz_id): def add_topic(request, content_type, course_id, lesson_id, toc_id=None, topic_id=None): user = request.user + if not is_moderator(user): + raise Http404('You are not allowed to view this page!') course = get_object_or_404(Course, pk=course_id) - if (not is_moderator(user) or - not course.is_creator(user) or not course.is_creator(user)): - raise Http404("You are not allowed to view this page") + if not course.is_creator(user) and not course.is_teacher(user): + raise Http404('This course does not belong to you') if topic_id: topic = get_object_or_404(Topic, pk=topic_id) else: @@ -3668,10 +3670,11 @@ def add_topic(request, content_type, course_id, lesson_id, toc_id=None, def add_marker_quiz(request, content_type, course_id, lesson_id, toc_id=None, question_id=None): user = request.user + if not is_moderator(user): + raise Http404('You are not allowed to view this page!') course = get_object_or_404(Course, pk=course_id) - if (not is_moderator(user) or - not course.is_creator(user) or not course.is_creator(user)): - raise Http404("You are not allowed to view this page") + if not course.is_creator(user) and not course.is_teacher(user): + raise Http404('This course does not belong to you') if question_id: question = get_object_or_404(Question, pk=question_id) else: @@ -3761,10 +3764,11 @@ def revoke_special_attempt(request, micromanager_id): @email_verified def delete_toc(request, course_id, toc_id): user = request.user + if not is_moderator(user): + raise Http404('You are not allowed to view this page!') course = get_object_or_404(Course, pk=course_id) - if (not is_moderator(user) or - not course.is_creator(user) or not course.is_creator(user)): - raise Http404("You are not allowed to view this page") + if not course.is_creator(user) and not course.is_teacher(user): + raise Http404('This course does not belong to you') toc = get_object_or_404(TableOfContents, pk=toc_id) redirect_url = request.POST.get("redirect_url") if toc.content == 1: @@ -3902,10 +3906,11 @@ def submit_marker_quiz(request, course_id, toc_id): @email_verified def lesson_statistics(request, course_id, lesson_id, toc_id=None): user = request.user + if not is_moderator(user): + raise Http404('You are not allowed to view this page!') course = get_object_or_404(Course, pk=course_id) - if (not is_moderator(user) or - not course.is_creator(user) or not course.is_creator(user)): - raise Http404("You are not allowed to view this page") + if not course.is_creator(user) and not course.is_teacher(user): + raise Http404('This course does not belong to you') context = {} lesson = get_object_or_404(Lesson, id=lesson_id) data = TableOfContents.objects.get_data(course_id, lesson_id) -- cgit From 86be5fd441b92a7679eb2b8673bfba2c188ba0ba Mon Sep 17 00:00:00 2001 From: adityacp Date: Wed, 30 Sep 2020 17:02:19 +0530 Subject: Add table of contents for lesson with yaml upload --- yaksh/views.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'yaksh/views.py') diff --git a/yaksh/views.py b/yaksh/views.py index a3d7def..9cca425 100644 --- a/yaksh/views.py +++ b/yaksh/views.py @@ -24,6 +24,7 @@ import json from textwrap import dedent import zipfile import markdown +import ruamel try: from StringIO import StringIO as string_io except ImportError: @@ -2710,6 +2711,26 @@ def edit_lesson(request, course_id=None, module_id=None, lesson_id=None): request, "Please select atleast one file to delete" ) + if 'upload_toc' in request.POST: + toc_file = request.FILES.get('toc') + file_extension = os.path.splitext(toc_file.name)[1][1:] + if file_extension not in ['yaml', 'yml']: + messages.warning( + request, "Please upload yaml or yml type file" + ) + else: + try: + toc_data = ruamel.yaml.safe_load_all(toc_file.read()) + results = TableOfContents.objects.add_contents( + course_id, lesson_id, user, toc_data) + for status, msg in results: + if status == True: + messages.success(request, msg) + else: + messages.warning(request, msg) + except Exception as e: + messages.warning(request, f"Error parsing yaml: {e}") + contents = TableOfContents.objects.filter( course_id=course_id, lesson_id=lesson_id ).order_by("time") -- cgit From c6c57869fe653d2ea0502017a9fb15f2f745491b Mon Sep 17 00:00:00 2001 From: adityacp Date: Wed, 30 Sep 2020 19:14:38 +0530 Subject: Change multiple files - Add download sample yaml for toc in the lesson - Add validation for upload toc yaml - Add tests for download sample yaml toc --- yaksh/views.py | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) (limited to 'yaksh/views.py') diff --git a/yaksh/views.py b/yaksh/views.py index 9cca425..73979da 100644 --- a/yaksh/views.py +++ b/yaksh/views.py @@ -2583,7 +2583,23 @@ def download_sample_csv(request): with open(csv_file_path, 'rb') as csv_file: response = HttpResponse(csv_file.read(), content_type='text/csv') response['Content-Disposition'] = ( - 'attachment; filename="sample_user_upload"' + 'attachment; filename="sample_user_upload.csv"' + ) + return response + + +@login_required +@email_verified +def download_sample_toc(request): + user = request.user + if not is_moderator(user): + raise Http404('You are not allowed to view this page!') + csv_file_path = os.path.join(FIXTURES_DIR_PATH, + "sample_lesson_toc.yaml") + with open(csv_file_path, 'rb') as csv_file: + response = HttpResponse(csv_file.read(), content_type='text/yaml') + response['Content-Disposition'] = ( + 'attachment; filename="sample_lesson_toc.yaml"' ) return response @@ -2731,13 +2747,7 @@ def edit_lesson(request, course_id=None, module_id=None, lesson_id=None): except Exception as e: messages.warning(request, f"Error parsing yaml: {e}") - contents = TableOfContents.objects.filter( - course_id=course_id, lesson_id=lesson_id - ).order_by("time") - data = loader.render_to_string( - "yaksh/show_toc.html", context={'contents': contents}, - request=request - ) + data = get_toc_contents(request, course_id, lesson_id) context['toc'] = data lesson_files = LessonFile.objects.filter(lesson=lesson) context['lesson_form'] = lesson_form @@ -3591,7 +3601,9 @@ def get_toc_contents(request, course_id, lesson_id): course_id=course_id, lesson_id=lesson_id ).order_by("time") data = loader.render_to_string( - "yaksh/show_toc.html", context={'contents': contents}, + "yaksh/show_toc.html", context={ + 'contents': contents, 'lesson_id': lesson_id + }, request=request ) return data -- cgit