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/forms.py | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 91 insertions(+), 1 deletion(-) (limited to 'yaksh/forms.py') diff --git a/yaksh/forms.py b/yaksh/forms.py index 3c4d664..797f54e 100644 --- a/yaksh/forms.py +++ b/yaksh/forms.py @@ -1,7 +1,8 @@ from django import forms from yaksh.models import ( get_model_class, Profile, Quiz, Question, Course, QuestionPaper, Lesson, - LearningModule, TestCase, languages, question_types, Post, Comment + LearningModule, TestCase, languages, question_types, Post, Comment, + Topic ) from grades.models import GradingSystem from django.contrib.auth import authenticate @@ -15,6 +16,8 @@ except ImportError: from string import ascii_letters as letters from string import punctuation, digits import pytz +from ast import literal_eval + from .send_emails import generate_activation_key languages = (("", "Select Language"),) + languages @@ -520,6 +523,13 @@ class LessonForm(forms.ModelForm): self.fields['description'].widget.attrs.update( {'class': form_input_class, 'placeholder': des_msg} ) + self.fields['video_path'].widget.attrs.update( + {'class': form_input_class, + 'placeholder': dedent("""\ + {'youtube': '', 'vimeo': '', 'others': ''} + """), + } + ) self.fields['video_file'].widget.attrs.update( {'class': "custom-file-input"} ) @@ -540,6 +550,26 @@ class LessonForm(forms.ModelForm): ) return file + def clean_video_path(self): + path = self.cleaned_data.get("video_path") + if path: + try: + value = literal_eval(path) + if not isinstance(value, dict): + raise forms.ValidationError( + "Value must be dictionary as shown in sample" + ) + else: + if len(value) > 1: + raise forms.ValidationError( + "Only one of the video name should be entered" + ) + except ValueError: + raise forms.ValidationError( + "Value must be dictionary as shown in sample" + ) + return path + class LessonFileForm(forms.Form): Lesson_files = forms.FileField( @@ -615,3 +645,63 @@ class CommentForm(forms.ModelForm): } ) } + + +class TopicForm(forms.ModelForm): + + timer = forms.CharField() + def __init__(self, *args, **kwargs): + super(TopicForm, self).__init__(*args, **kwargs) + self.fields['name'].widget.attrs.update( + {'class': form_input_class, 'placeholder': 'Topic Name'} + ) + self.fields['timer'].widget.attrs.update( + {'class': form_input_class, 'placeholder': 'Topic Time'} + ) + + class Meta: + model = Topic + fields = "__all__" + + +class VideoQuizForm(forms.ModelForm): + + _types = dict(question_types) + + type = forms.CharField() + + timer = forms.CharField() + + def __init__(self, *args, **kwargs): + if 'question_type' in kwargs: + question_type = kwargs.pop('question_type') + else: + question_type = "mcq" + super(VideoQuizForm, self).__init__(*args, **kwargs) + self.fields['summary'].widget.attrs.update( + {'class': form_input_class, 'placeholder': 'Summary'} + ) + self.fields['language'].widget.attrs.update( + {'class': 'custom-select'} + ) + self.fields['topic'].widget.attrs.update( + {'class': form_input_class, 'placeholder': 'Question topic name'} + ) + self.fields['points'].widget.attrs.update( + {'class': form_input_class, 'placeholder': 'Points'} + ) + self.fields['type'].widget.attrs.update( + {'class': form_input_class, 'readonly': True} + ) + self.fields['type'].initial = self._types.get(question_type) + self.fields['description'].widget.attrs.update( + {'class': form_input_class, 'placeholder': 'Description'} + ) + self.fields['timer'].widget.attrs.update( + {'class': form_input_class, 'placeholder': 'Quiz Time'} + ) + + class Meta: + model = Question + fields = ['summary', 'description', 'points', + 'language', 'type', 'topic'] -- 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/forms.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'yaksh/forms.py') diff --git a/yaksh/forms.py b/yaksh/forms.py index 797f54e..eedd809 100644 --- a/yaksh/forms.py +++ b/yaksh/forms.py @@ -650,6 +650,7 @@ class CommentForm(forms.ModelForm): class TopicForm(forms.ModelForm): timer = forms.CharField() + def __init__(self, *args, **kwargs): super(TopicForm, self).__init__(*args, **kwargs) self.fields['name'].widget.attrs.update( @@ -666,8 +667,6 @@ class TopicForm(forms.ModelForm): class VideoQuizForm(forms.ModelForm): - _types = dict(question_types) - type = forms.CharField() timer = forms.CharField() @@ -693,7 +692,7 @@ class VideoQuizForm(forms.ModelForm): self.fields['type'].widget.attrs.update( {'class': form_input_class, 'readonly': True} ) - self.fields['type'].initial = self._types.get(question_type) + self.fields['type'].initial = question_type self.fields['description'].widget.attrs.update( {'class': form_input_class, 'placeholder': 'Description'} ) -- 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/forms.py | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) (limited to 'yaksh/forms.py') diff --git a/yaksh/forms.py b/yaksh/forms.py index eedd809..ba8b7d5 100644 --- a/yaksh/forms.py +++ b/yaksh/forms.py @@ -652,6 +652,7 @@ class TopicForm(forms.ModelForm): timer = forms.CharField() def __init__(self, *args, **kwargs): + time = kwargs.pop("time") if "time" in kwargs else None super(TopicForm, self).__init__(*args, **kwargs) self.fields['name'].widget.attrs.update( {'class': form_input_class, 'placeholder': 'Topic Name'} @@ -659,11 +660,23 @@ class TopicForm(forms.ModelForm): self.fields['timer'].widget.attrs.update( {'class': form_input_class, 'placeholder': 'Topic Time'} ) + self.fields['timer'].initial = time class Meta: model = Topic fields = "__all__" + def clean_timer(self): + timer = self.cleaned_data.get("timer") + if timer: + try: + hh, mm, ss = timer.split(":") + except ValueError: + raise forms.ValidationError( + "Marker time should be in the format hh:mm:ss" + ) + return timer + class VideoQuizForm(forms.ModelForm): @@ -676,6 +689,7 @@ class VideoQuizForm(forms.ModelForm): question_type = kwargs.pop('question_type') else: question_type = "mcq" + time = kwargs.pop("time") if "time" in kwargs else None super(VideoQuizForm, self).__init__(*args, **kwargs) self.fields['summary'].widget.attrs.update( {'class': form_input_class, 'placeholder': 'Summary'} @@ -690,7 +704,7 @@ class VideoQuizForm(forms.ModelForm): {'class': form_input_class, 'placeholder': 'Points'} ) self.fields['type'].widget.attrs.update( - {'class': form_input_class, 'readonly': True} + {'class': form_input_class} ) self.fields['type'].initial = question_type self.fields['description'].widget.attrs.update( @@ -699,8 +713,20 @@ class VideoQuizForm(forms.ModelForm): self.fields['timer'].widget.attrs.update( {'class': form_input_class, 'placeholder': 'Quiz Time'} ) + self.fields['timer'].initial = time class Meta: model = Question fields = ['summary', 'description', 'points', 'language', 'type', 'topic'] + + def clean_timer(self): + timer = self.cleaned_data.get("timer") + if timer: + try: + hh, mm, ss = timer.split(":") + except ValueError: + raise forms.ValidationError( + "Marker time should be in the format hh:mm:ss" + ) + return timer \ No newline at end of file -- 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/forms.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'yaksh/forms.py') 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( -- 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/forms.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'yaksh/forms.py') diff --git a/yaksh/forms.py b/yaksh/forms.py index 440a535..cc5daaf 100644 --- a/yaksh/forms.py +++ b/yaksh/forms.py @@ -655,10 +655,13 @@ class TopicForm(forms.ModelForm): time = kwargs.pop("time") if "time" in kwargs else None super(TopicForm, self).__init__(*args, **kwargs) self.fields['name'].widget.attrs.update( - {'class': form_input_class, 'placeholder': 'Topic Name'} + {'class': form_input_class, 'placeholder': 'Name'} ) self.fields['timer'].widget.attrs.update( - {'class': form_input_class, 'placeholder': 'Topic Time'} + {'class': form_input_class, 'placeholder': 'Time'} + ) + self.fields['description'].widget.attrs.update( + {'class': form_input_class, 'placeholder': 'Description'} ) self.fields['timer'].initial = time -- cgit From 0c5f2afb084c0a4efd1715d53909ce2bb07b5883 Mon Sep 17 00:00:00 2001 From: adityacp Date: Fri, 25 Sep 2020 10:33:47 +0530 Subject: Change forms, models, settings and template - Add max_upload_size in settings for video file - Change error messages in forms - Set the video_file field max_length - Fix add_lesson template for uploading video file --- yaksh/forms.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'yaksh/forms.py') diff --git a/yaksh/forms.py b/yaksh/forms.py index cc5daaf..c179081 100644 --- a/yaksh/forms.py +++ b/yaksh/forms.py @@ -9,6 +9,7 @@ from django.contrib.auth import authenticate from django.contrib.auth.models import User from django.conf import settings from django.utils import timezone +from django.template.defaultfilters import filesizeformat from textwrap import dedent try: from string import letters @@ -530,9 +531,6 @@ class LessonForm(forms.ModelForm): """), } ) - self.fields['video_file'].widget.attrs.update( - {'class': "custom-file-input"} - ) class Meta: model = Lesson @@ -548,6 +546,12 @@ class LessonForm(forms.ModelForm): "Please upload video files in {0} format".format( ", ".join(actual_extension)) ) + if file.size > settings.MAX_UPLOAD_SIZE: + raise forms.ValidationError( + f"Video file size must be less than "\ + f"{filesizeformat(settings.MAX_UPLOAD_SIZE)}. " + f"Current size is {filesizeformat(file.size)}" + ) return file def clean_video_path(self): @@ -557,16 +561,16 @@ class LessonForm(forms.ModelForm): value = literal_eval(path) if not isinstance(value, dict): raise forms.ValidationError( - "Value must be dictionary as shown in sample" + "Value must be dictionary e.g {'youtube': 'video-id'}" ) else: if len(value) > 1: raise forms.ValidationError( - "Only one of the video name should be entered" + "Only one type of video path is allowed" ) except ValueError: raise forms.ValidationError( - "Value must be dictionary as shown in sample" + "Value must be dictionary e.g {'youtube': 'video-id'}" ) return path -- cgit