From fe70769afcdf239577d59e330e32306d14107a48 Mon Sep 17 00:00:00 2001 From: ankitjavalkar Date: Mon, 8 Jun 2020 11:20:48 +0530 Subject: - Remove Copy Of in Module, Lesson and Quiz names when duplicating courses - Prevent student users from accessing Questions --- yaksh/models.py | 6 +++--- yaksh/views.py | 3 +++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/yaksh/models.py b/yaksh/models.py index 7d4dd98..e86472c 100644 --- a/yaksh/models.py +++ b/yaksh/models.py @@ -296,7 +296,7 @@ class Lesson(models.Model): lesson_files = self.get_files() new_lesson = self new_lesson.id = None - new_lesson.name = "Copy of {0}".format(self.name) + new_lesson.name = self.name new_lesson.creator = user new_lesson.save() for _file in lesson_files: @@ -575,7 +575,7 @@ class Quiz(models.Model): question_papers = self.questionpaper_set.all() new_quiz = self new_quiz.id = None - new_quiz.description = "Copy of {0}".format(self.description) + new_quiz.description = self.description new_quiz.creator = user new_quiz.save() for qp in question_papers: @@ -932,7 +932,7 @@ class Course(models.Model): copy_course_name = "Copy Of {0}".format(self.name) new_course = self._create_duplicate_instance(user, copy_course_name) for module in learning_modules: - copy_module_name = "Copy of {0}".format(module.name) + copy_module_name = module.name new_module = module._create_module_copy(user, copy_module_name) new_course.learning_module.add(new_module) return new_course diff --git a/yaksh/views.py b/yaksh/views.py index 3adb536..1544508 100644 --- a/yaksh/views.py +++ b/yaksh/views.py @@ -224,6 +224,9 @@ def results_user(request): @email_verified def add_question(request, question_id=None): user = request.user + if not is_moderator(user): + raise Http404('You are not allowed to view this page !') + test_case_type = None if question_id is not None: -- cgit From db974d80d0ec308d17c6c0099576d24f3e0ed98a Mon Sep 17 00:00:00 2001 From: ankitjavalkar Date: Tue, 9 Jun 2020 11:09:07 +0530 Subject: Fix test cases --- yaksh/test_views.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/yaksh/test_views.py b/yaksh/test_views.py index a7ccac2..3a42cf5 100644 --- a/yaksh/test_views.py +++ b/yaksh/test_views.py @@ -2166,7 +2166,8 @@ class TestCourses(TestCase): # Teacher Login # Given # Add files to a lesson - lesson_file = SimpleUploadedFile("file1.txt", b"Test") + file_content = b"Test" + lesson_file = SimpleUploadedFile("file1.txt", file_content) django_file = File(lesson_file) lesson_file_obj = LessonFile() lesson_file_obj.lesson = self.lesson @@ -2201,18 +2202,18 @@ class TestCourses(TestCase): self.assertEqual(response.status_code, 200) self.assertEqual(courses.last().creator, self.teacher) self.assertEqual(courses.last().name, "Copy Of Python Course") - self.assertEqual(module.name, "Copy of demo module") + self.assertEqual(module.name, "demo module") self.assertEqual(module.creator, self.teacher) self.assertEqual(module.order, 0) self.assertEqual(len(units), 2) - self.assertEqual(cloned_lesson.name, "Copy of demo lesson") + self.assertEqual(cloned_lesson.name, "demo lesson") self.assertEqual(cloned_lesson.creator, self.teacher) - self.assertEqual(cloned_quiz.description, "Copy of demo quiz") + self.assertEqual(cloned_quiz.description, "demo quiz") self.assertEqual(cloned_quiz.creator, self.teacher) self.assertEqual(cloned_qp.__str__(), - "Question Paper for Copy of demo quiz") - self.assertEqual(os.path.basename(expected_lesson_files[0].file.name), - os.path.basename(actual_lesson_files[0].file.name)) + "Question Paper for demo quiz") + self.assertTrue(expected_lesson_files.exists()) + self.assertEquals(expected_lesson_files[0].file.read(), file_content) for lesson_file in self.all_files: file_path = lesson_file.file.path -- cgit From 49a494849a0498e309f6c97ec6ae6ab79961b87d Mon Sep 17 00:00:00 2001 From: ankitjavalkar Date: Thu, 30 Jul 2020 22:14:44 +0530 Subject: Make changes based on feedback --- yaksh/models.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/yaksh/models.py b/yaksh/models.py index e86472c..87a6877 100644 --- a/yaksh/models.py +++ b/yaksh/models.py @@ -296,7 +296,6 @@ class Lesson(models.Model): lesson_files = self.get_files() new_lesson = self new_lesson.id = None - new_lesson.name = self.name new_lesson.creator = user new_lesson.save() for _file in lesson_files: @@ -575,7 +574,6 @@ class Quiz(models.Model): question_papers = self.questionpaper_set.all() new_quiz = self new_quiz.id = None - new_quiz.description = self.description new_quiz.creator = user new_quiz.save() for qp in question_papers: @@ -821,12 +819,13 @@ class LearningModule(models.Model): percent = round((count / units.count()) * 100) return percent - def _create_module_copy(self, user, module_name): + def _create_module_copy(self, user, module_name=None): learning_units = self.learning_unit.order_by("order") new_module = self new_module.id = None - new_module.name = module_name new_module.creator = user + if module_name: + new_module.name = module_name new_module.save() for unit in learning_units: new_unit = unit._create_unit_copy(user) @@ -933,7 +932,7 @@ class Course(models.Model): new_course = self._create_duplicate_instance(user, copy_course_name) for module in learning_modules: copy_module_name = module.name - new_module = module._create_module_copy(user, copy_module_name) + new_module = module._create_module_copy(user) new_course.learning_module.add(new_module) return new_course -- cgit From 55d2800b61df661e7155f8b3cbd30ed047259f43 Mon Sep 17 00:00:00 2001 From: Jayram Date: Sun, 9 Aug 2020 22:16:56 +0530 Subject: [FIX] #546 - create_moderator command if User has no Profile --- yaksh/management/commands/create_moderator.py | 5 +++++ yaksh/models.py | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/yaksh/management/commands/create_moderator.py b/yaksh/management/commands/create_moderator.py index 3ec012e..c0f160a 100644 --- a/yaksh/management/commands/create_moderator.py +++ b/yaksh/management/commands/create_moderator.py @@ -10,6 +10,7 @@ from django.contrib.auth.models import User, Group, Permission # local imports from yaksh.models import create_group +from yaksh.views import _create_or_update_profile class Command(BaseCommand): @@ -43,6 +44,10 @@ class Command(BaseCommand): ) ) else: + if not hasattr(user, 'profile'): + _create_or_update_profile(user, + {'is_email_verified': True} + ) user.profile.is_moderator = True user.profile.save() self.stdout.write( diff --git a/yaksh/models.py b/yaksh/models.py index 6542daa..0765ee8 100644 --- a/yaksh/models.py +++ b/yaksh/models.py @@ -1279,7 +1279,7 @@ class Profile(models.Model): super(Profile, self).save(*args, **kwargs) def __str__(self): - return '%s' % (self.user.get_full_name()) + return '%s' % (self.user.get_full_name() or self.user.username) ############################################################################### -- cgit From d6fe6e10d13631998135c825e1f0cba3f3ffeb61 Mon Sep 17 00:00:00 2001 From: CruiseDevice Date: Fri, 25 Sep 2020 00:26:39 +0530 Subject: Add TinyMCE, fix minor progressbar issues --- grades/templates/add_grades.html | 5 +++ yaksh/static/yaksh/js/add_course.js | 16 ++++++++ yaksh/static/yaksh/js/add_grades.js | 14 +++++++ yaksh/static/yaksh/js/add_quiz.js | 13 +++++- yaksh/static/yaksh/js/lesson.js | 14 +++++++ yaksh/templates/yaksh/add_course.html | 2 + yaksh/templates/yaksh/add_lesson.html | 4 +- yaksh/templates/yaksh/add_module.html | 20 ++++----- yaksh/templates/yaksh/add_quiz.html | 1 + yaksh/templates/yaksh/user_status.html | 75 +++++++++++++++++++++++++++------- 10 files changed, 136 insertions(+), 28 deletions(-) create mode 100644 yaksh/static/yaksh/js/add_course.js create mode 100644 yaksh/static/yaksh/js/add_grades.js diff --git a/grades/templates/add_grades.html b/grades/templates/add_grades.html index 198eb4b..c7006a9 100644 --- a/grades/templates/add_grades.html +++ b/grades/templates/add_grades.html @@ -1,7 +1,12 @@ {% extends "manage.html" %} +{% load static %} {% load custom_filters %} {% block title %} Add/Edit Grading {% endblock %} {% block pagetitle %} Add/Edit Grading {% endblock %} +{% block script %} + + +{% endblock %} {% block main %}
Sr No. | +Student Name | +Last access on | +Started on | +Current Time | +Video Duration | +Percentage watched | +
---|---|---|---|---|---|---|
{{ forloop.counter0|add:objects.start_index }} | +{{track.user.get_full_name}} | +{{track.last_access_time}} | +{{track.creation_time}} | +{{track.current_time}} | +{{track.video_duration}} | ++ + | +
{{comment.description|safe}}
-- cgit From 6b5b21fc26879c1724bf02952584196f6c302b91 Mon Sep 17 00:00:00 2001 From: adityacp Date: Sat, 7 Nov 2020 11:58:22 +0530 Subject: Add tests for lesson tracking --- .sampleenv | 13 ++++++ .travis.yml | 1 + stats/tests.py | 139 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- stats/views.py | 1 + 4 files changed, 152 insertions(+), 2 deletions(-) create mode 100644 .sampleenv diff --git a/.sampleenv b/.sampleenv new file mode 100644 index 0000000..a31ec1f --- /dev/null +++ b/.sampleenv @@ -0,0 +1,13 @@ +# Django settings +SECRET_KEY=dUmMy_s3cR3t_k3y +#DB_ENGINE=mysql +#DB_NAME=yaksh +#DB_USER=root +#DB_PASSWORD=root +#DB_HOST=yaksh-db +#DB_PORT=3306 +# Yaksh settings +N_CODE_SERVERS=5 +#SERVER_POOL_PORT=53579 +#SERVER_HOST_NAME=http://yaksh-codeserver +#SERVER_TIMEOUT=4 diff --git a/.travis.yml b/.travis.yml index fd0746c..d7e63e8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -29,6 +29,7 @@ before_script: script: - coverage erase - coverage run -p manage.py test -v 2 yaksh + - coverage run -p manage.py test -v 2 stats - coverage run -p manage.py test -v 2 grades - coverage run -p manage.py test -v 2 yaksh.live_server_tests.load_test - coverage run -p manage.py test -v 2 api diff --git a/stats/tests.py b/stats/tests.py index 7ce503c..c256feb 100644 --- a/stats/tests.py +++ b/stats/tests.py @@ -1,3 +1,138 @@ -from django.test import TestCase +# Python Imports +import json + +# Django Imports +from django.test import TestCase, Client +from django.contrib.auth.models import User, Group +from django.urls import reverse + +# Local Imports +from stats.models import TrackLesson +from yaksh.models import Course, Lesson, LearningUnit, LearningModule + + +class TestTrackLesson(TestCase): + def setUp(self): + self.client = Client() + self.mod_group, created = Group.objects.get_or_create(name='moderator') + self.user_plaintext_pass = 'demo' + self.user = User.objects.create_user( + username='demo_user', + password=self.user_plaintext_pass, + first_name='first_name', + last_name='last_name', + email='demo@test.com', + ) + + # Create Student + self.student_plaintext_pass = 'demo_student' + self.student = User.objects.create_user( + username='demo_student', + password=self.student_plaintext_pass, + first_name='student_first_name', + last_name='student_last_name', + email='demo_student@test.com' + ) + + # Add to moderator group + self.mod_group.user_set.add(self.user) + + self.course = Course.objects.create( + name="Test_course", + enrollment="Open Enrollment", creator=self.user + ) + self.lesson = Lesson.objects.create( + name="Test_lesson", description="test description", + creator=self.user) + self.learning_unit = LearningUnit.objects.create( + order=0, type="lesson", lesson=self.lesson + ) + self.learning_module = LearningModule.objects.create( + order=0, name="Test_module", description="Demo module", + check_prerequisite=False, creator=self.user + ) + self.learning_module.learning_unit.add(self.learning_unit.id) + self.track = TrackLesson.objects.create( + user_id=self.student.id, course_id=self.course.id, + lesson_id=self.lesson.id + ) + + def tearDown(self): + self.client.logout() + self.mod_group.delete() + self.user.delete() + self.student.delete() + self.course.delete() + self.learning_unit.delete() + self.learning_module.delete() + + def test_add_video_track(self): + self.client.login( + username=self.student.username, + password=self.student_plaintext_pass + ) + + # Student not enrolled in the course fails to add the tracking + response = self.client.post( + reverse('stats:add_tracker', + kwargs={"tracker_id": self.track.id}), + data={'video_duration': '00:05:00'} + ) + self.assertEqual(response.status_code, 404) + + self.course.students.add(self.student.id) + # No current time given in the post data + response = self.client.post( + reverse('stats:add_tracker', + kwargs={"tracker_id": self.track.id}), + data={'video_duration': '00:05:00'} + ) + self.assertEqual(response.status_code, 200) + self.assertFalse(response.json().get('success')) + + # Valid post data + response = self.client.post( + reverse('stats:add_tracker', + kwargs={"tracker_id": self.track.id}), + data={'video_duration': '00:05:00', + 'current_video_time': '00:01:00'} + ) + + self.assertEqual(response.status_code, 200) + self.assertTrue(response.json().get('success')) + + def test_disallow_student_view_tracking(self): + self.client.login( + username=self.student.username, + password=self.student_plaintext_pass + ) + + # Fails to view the lesson data for student + response = self.client.get( + reverse('stats:view_lesson_watch_stats', + kwargs={"course_id": self.course.id, + "lesson_id": self.lesson.id}) + ) + self.assertEqual(response.status_code, 404) + + def test_allow_moderator_view_tracking(self): + self.client.login( + username=self.user.username, + password=self.user_plaintext_pass + ) + # Course creator can view the lesson data + response = self.client.get( + reverse('stats:view_lesson_watch_stats', + kwargs={"course_id": self.course.id, + "lesson_id": self.lesson.id}) + ) + response_data = response.context + self.assertEqual(response.status_code, 200) + self.assertEqual(response_data.get('total'), 1) + expected_tracker = list(TrackLesson.objects.filter( + user_id=self.student.id, course_id=self.course.id, + lesson_id=self.lesson.id).values_list("id", flat=True)) + obtained_tracker = list(response_data.get( + 'objects').object_list.values_list("id", flat=True)) + self.assertEqual(obtained_tracker, expected_tracker) -# Create your tests here. diff --git a/stats/views.py b/stats/views.py index ddbc1b3..3bfe9c3 100644 --- a/stats/views.py +++ b/stats/views.py @@ -4,6 +4,7 @@ from django.http import JsonResponse from django.utils import timezone from django.contrib.auth.decorators import login_required from django.core.paginator import Paginator +from django.http import Http404 # Local Imports from stats.models import TrackLesson -- cgit From 7419b67b1928f30824a332d36afcdfddebaf2479 Mon Sep 17 00:00:00 2001 From: adityacp Date: Sat, 7 Nov 2020 12:09:22 +0530 Subject: Add table sorter --- stats/templates/view_lesson_tracking.html | 34 ++++++++++++++++--------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/stats/templates/view_lesson_tracking.html b/stats/templates/view_lesson_tracking.html index fd87d70..fa891e3 100644 --- a/stats/templates/view_lesson_tracking.html +++ b/stats/templates/view_lesson_tracking.html @@ -1,7 +1,9 @@ {% extends "manage.html" %} - +{% load static %} {% block title %} Lesson Views {% endblock %} {% block script %} + {% endblock %} @@ -49,22 +40,22 @@+ | {{forloop.counter}} | +{% if unit.type == "quiz" %} {% if unit.quiz.is_exercise %} @@ -69,12 +71,12 @@ {% if quiz.questionpaper_set.get.id %} - Edit Question Paper + Question Paper {% else %} - Add Question Paper + Question Paper {% endif %} {% endwith %} @@ -93,6 +95,14 @@ Lesson {% endif %} | ++ {% if unit.type == "quiz" %} + ---- + {% else %} + {% get_lesson_views course.id unit.lesson.id as views %} + {{views.0}} views out of {{views.1}} + {% endif %} + |
{% if unit.type == "quiz" %}
{% if unit.quiz.questionpaper_set.get.id %}
@@ -104,9 +114,23 @@
----
{% endif %}
{% else %}
-
- Statistics
+
+
{% endif %}
+
+ |
Sr No. | -Student Name | -Latest Submission | +Student Name | +Latest Submission | ||
---|---|---|---|---|---|---|
{{ forloop.counter0|add:objects.start_index }} | +{{ forloop.counter }} | {{data.student__first_name}} {{data.student__last_name}} | {{data.student__email}} | {% get_answers data.toc_id data.student_id as user_answer %} diff --git a/yaksh/templates/yaksh/show_video.html b/yaksh/templates/yaksh/show_video.html index 0151f6b..b4f5628 100644 --- a/yaksh/templates/yaksh/show_video.html +++ b/yaksh/templates/yaksh/show_video.html @@ -9,6 +9,8 @@ var contents_by_time = JSON.parse('{{ contents_by_time|safe }}'); var loc = 0; var video_time = []; + var markers = []; + var track_count = 0; diff --git a/yaksh/templatetags/custom_filters.py b/yaksh/templatetags/custom_filters.py index a3cd3f1..91681c2 100644 --- a/yaksh/templatetags/custom_filters.py +++ b/yaksh/templatetags/custom_filters.py @@ -11,7 +11,11 @@ except ImportError: from pygments import highlight from pygments.lexers import get_lexer_by_name from pygments.formatters import HtmlFormatter + +# Local Imports from yaksh.models import User, Course, Quiz, TableOfContents, Lesson +from stats.models import TrackLesson + register = template.Library() @@ -200,3 +204,10 @@ def has_lesson_video(lesson_id): def get_tc_percent(tc_id, data): return data.get(str(tc_id), 0) + +@register.simple_tag +def get_lesson_views(course_id, lesson_id): + course = Course.objects.get(id=course_id) + return TrackLesson.objects.filter( + course_id=course_id, lesson_id=lesson_id + ).count(), course.students.count() -- cgit From eab5482d486a5aefdabb7ff3598bfaa7b71b3178 Mon Sep 17 00:00:00 2001 From: adityacp Date: Thu, 19 Nov 2020 12:52:23 +0530 Subject: Release changes --- CHANGELOG.txt | 15 +++++++++++++++ online_test/__init__.py | 2 +- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 87a2c47..d6232cb 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,3 +1,18 @@ +=== 0.29.2 (19-11-2020) === + +* Add dropdown selection for lesson video options +* Show total visits per student in lesson statistics. +* Remove settimeout ajax calls for tracking video positions. +* Show initial views per lesson in the course modules section. +* Add tinymce editor for all the textareas. + +=== 0.29.1 (12-11-2020) === + +* Fixed issue onclick toc jump to player time. +* Used bootstrap modal instead of jquery dialog for responsive interface. +* Disallow empty question submission for lesson quiz. +* Fixed issue where the videos other than youtube does not get the duration. + === 0.29.0 (07-11-2020) === * Add feature to track lesson video views diff --git a/online_test/__init__.py b/online_test/__init__.py index c96a9aa..41b7f9c 100644 --- a/online_test/__init__.py +++ b/online_test/__init__.py @@ -4,4 +4,4 @@ from online_test.celery_settings import app as celery_app __all__ = ('celery_app',) -__version__ = '0.29.0' +__version__ = '0.29.2' -- cgit From 60503c9bd1ea49177f0adfc39ff129bfba86c9de Mon Sep 17 00:00:00 2001 From: prathamesh Date: Fri, 27 Nov 2020 04:18:27 +0530 Subject: Fix answer paper view. - Slight optimisation in retrieving and rendering the data - avoids the arrange type question's custom filter error - Marks obtained appears properly on all the interface(user view answerpaper, monitor and grade user) - if not attempted then shows the question and says "Did not attempt" --- yaksh/models.py | 55 +++++++++++------------------ yaksh/templates/yaksh/grade_user.html | 14 ++++---- yaksh/templates/yaksh/user_data.html | 17 +++++---- yaksh/templates/yaksh/view_answerpaper.html | 14 ++++---- 4 files changed, 43 insertions(+), 57 deletions(-) diff --git a/yaksh/models.py b/yaksh/models.py index 50e9363..2978f43 100644 --- a/yaksh/models.py +++ b/yaksh/models.py @@ -2321,14 +2321,20 @@ class AnswerPaper(models.Model): secs = dt.seconds + dt.days*24*3600 return secs + def _get_marks_for_question(self, question): + marks = 0.0 + answers = question.answer_set.filter(answerpaper=self) + if answers.exists(): + marks = [answer.marks for answer in answers] + max_marks = max(marks) + marks = max_marks + return marks + def _update_marks_obtained(self): """Updates the total marks earned by student for this paper.""" - marks = 0 + marks = 0.0 for question in self.questions.all(): - marks_list = [a.marks - for a in self.answers.filter(question=question)] - max_marks = max(marks_list) if marks_list else 0.0 - marks += max_marks + marks += self._get_marks_for_question(question) self.marks_obtained = marks def _update_percent(self): @@ -2376,38 +2382,19 @@ class AnswerPaper(models.Model): corresponding answers. """ q_a = {} - for answer in self.answers.all(): - question = answer.question - if question in q_a: - q_a[question].append({ - 'answer': answer, - 'error_list': [e for e in json.loads(answer.error)] - }) - else: - q_a[question] = [{ + for question in self.questions.all(): + answers = question.answer_set.filter(answerpaper=self) + if not answers.exists(): + q_a[question] = [None, 0.0] + continue + ans_errs = [] + for answer in answers: + ans_errs.append({ 'answer': answer, 'error_list': [e for e in json.loads(answer.error)] - }] - - q_a.update( - { q: [] for q in self.questions_unanswered.all() } - ) - - for question, answers in q_a.items(): - answers = q_a[question] - if answers: - q_a[question].append({ - 'marks': max([ - answer['answer'].marks - for answer in answers - if question == answer['answer'].question - ]), }) - else: - q_a[question].append({ - 'marks': 0.0, - }) - + q_a[question] = ans_errs + q_a[question].append(self._get_marks_for_question(question)) return q_a def get_latest_answer(self, question_id): diff --git a/yaksh/templates/yaksh/grade_user.html b/yaksh/templates/yaksh/grade_user.html index 341fd7c..64b9cb5 100644 --- a/yaksh/templates/yaksh/grade_user.html +++ b/yaksh/templates/yaksh/grade_user.html @@ -319,7 +319,6 @@ function searchNames() {|||
@@ -327,14 +326,13 @@ function searchNames() { | {{ question.type }} | -{{ answer.marks }} | +{{ answers|last }} | Regrade |
Did not attempt
+ {% else %} + {% for ans in answers|slice:":-1" %} Attempt Number: {{forloop.counter}} @@ -559,6 +560,7 @@ function searchNames() {Did not attempt
+ {% else %} + {% for ans in answers|slice:":-1" %} Attempt Number: {{forloop.counter}} @@ -303,6 +303,7 @@Did not attempt
+ {% else %} + {% for ans in answers|slice:":-1" %} Attempt Number: {{forloop.counter}} @@ -324,6 +325,7 @@{{track.creation_time}} | {{track.get_current_time}} | {{track.get_video_duration}} | -{{track.get_percentage_complete}} | +{{track.get_percentage_complete}} % | {% with track.get_watched as watched %} {% if watched %} {{watched}} {% else %} - {{watched}} + {{watched}} {% endif %} {% endwith %} | diff --git a/stats/views.py b/stats/views.py index 53b7cf7..a5cdeb7 100644 --- a/stats/views.py +++ b/stats/views.py @@ -27,14 +27,14 @@ def add_tracker(request, tracker_id): if current_time: track.set_current_time(current_time) track.video_duration = video_duration - LessonLog.objects.create( - track_id=track.id, current_time=current_time, - last_access_time=timezone.now() - ) track.save() if not track.watched: track.set_watched() track.save() + LessonLog.objects.create( + track_id=track.id, current_time=current_time, + last_access_time=timezone.now() + ) success = True else: success = False @@ -46,16 +46,25 @@ def add_tracker(request, tracker_id): @email_verified def view_lesson_watch_stats(request, course_id, lesson_id): user = request.user - course = get_object_or_404(Course, pk=course_id) + course = get_object_or_404( + Course.objects.prefetch_related("students"), id=course_id + ) if not course.is_creator(user) and not course.is_teacher(user): raise Http404('This course does not belong to you') trackings = TrackLesson.objects.get_queryset().filter( course_id=course_id, lesson_id=lesson_id ).order_by("id") - total = trackings.count() + percentage_data = TrackLesson.objects.get_percentage_data(trackings) + visited = trackings.count() + completed = trackings.filter(watched=True).count() + students_total = course.students.count() paginator = Paginator(trackings, 30) page = request.GET.get('page') trackings = paginator.get_page(page) - context = {'objects': trackings, 'total': total, 'course_id': course_id, - 'lesson_id': lesson_id} + context = { + 'objects': trackings, 'total': visited, 'course_id': course_id, + 'lesson_id': lesson_id, "percentage_data": percentage_data, + 'completion': [completed, students_total-completed, students_total], + 'visits': [visited, students_total-visited, students_total] + } return render(request, 'view_lesson_tracking.html', context) diff --git a/yaksh/templates/yaksh/show_lesson_statistics.html b/yaksh/templates/yaksh/show_lesson_statistics.html index a7c2ebd..dfce52c 100644 --- a/yaksh/templates/yaksh/show_lesson_statistics.html +++ b/yaksh/templates/yaksh/show_lesson_statistics.html @@ -1,7 +1,7 @@ {% extends "manage.html" %} {% load static %} {% load custom_filters %} -{% block title %} Lesson Statistics {% endblock %} +{% block title %} Lesson Quiz Stats {% endblock %} {% block pagetitle %} Statistics for {{lesson}} {% endblock %} {% block script %}
Sr No. | Student Name | @@ -94,12 +95,13 @@Started on | Current Duration | Video Duration | -Percentage Watched | -Watched Once Completely | +Percentage | +Watched | Total Time Spent | Total Visits |
---|---|---|---|---|---|---|---|---|---|---|
{{ forloop.counter0 }} | @@ -122,7 +124,9 @@{{track.get_no_of_vists}} |
A beautiful Dashboard for Bootstrap 4. It is Free and Open Source.
A beautiful Dashboard for Bootstrap 4. It is Free and Open Source.