From 541f3ec154f7c484a2a9105565117cefa4e15b18 Mon Sep 17 00:00:00 2001 From: adityacp Date: Tue, 31 Mar 2020 14:46:19 +0530 Subject: Update the units and modules order on creation --- yaksh/models.py | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'yaksh/models.py') diff --git a/yaksh/models.py b/yaksh/models.py index 12c902b..52a0414 100644 --- a/yaksh/models.py +++ b/yaksh/models.py @@ -841,6 +841,15 @@ class LearningModule(models.Model): write_templates_to_zip(zip_file, module_file_path, module_data, module_name, folder_name) + def get_unit_order(self, type, unit): + if type == "lesson": + order = self.get_learning_units().get( + type=type, lesson=unit).order + else: + order = self.get_learning_units().get( + type=type, quiz=unit).order + return order + def __str__(self): return self.name -- cgit From ce3eb1dbbd924003489d01f4e98aba841cd803c0 Mon Sep 17 00:00:00 2001 From: adityacp Date: Wed, 8 Apr 2020 15:55:59 +0530 Subject: Change templates, views, forms, models - Allow to test, download and delete single question - Fix pagination for searching and filtering questions --- yaksh/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'yaksh/models.py') diff --git a/yaksh/models.py b/yaksh/models.py index 52a0414..5d4d453 100644 --- a/yaksh/models.py +++ b/yaksh/models.py @@ -1385,7 +1385,7 @@ class Question(models.Model): testcases.append(case.get_field_value()) q_dict['testcase'] = testcases q_dict['files'] = file_names - q_dict['tags'] = [tags.tag.name for tags in q_dict['tags']] + q_dict['tags'] = [tag.name for tag in q_dict['tags']] questions_dict.append(q_dict) question._add_yaml_to_zip(zip_file, questions_dict) return zip_file_name -- cgit From 2a9f81cb32acfd7a2efc18f58c4529b39ce4061b Mon Sep 17 00:00:00 2001 From: CruiseDevice Date: Sat, 11 Apr 2020 17:45:31 +0530 Subject: Discussion forum for a course --- yaksh/models.py | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) (limited to 'yaksh/models.py') diff --git a/yaksh/models.py b/yaksh/models.py index 52a0414..83c644a 100644 --- a/yaksh/models.py +++ b/yaksh/models.py @@ -1,5 +1,6 @@ from __future__ import unicode_literals, division from datetime import datetime, timedelta +import uuid import json import random import ruamel.yaml @@ -2633,3 +2634,40 @@ class TestCaseOrder(models.Model): order = models.TextField() ############################################################################## +class Thread(models.Model): + uid = models.UUIDField(unique=True, default=uuid.uuid4, editable=False) + creator = models.ForeignKey(User, on_delete=models.CASCADE) + title = models.CharField(max_length=200) + description = models.TextField() + course = models.ForeignKey(Course, + on_delete=models.CASCADE, related_name='thread') + created_at = models.DateTimeField(auto_now_add=True) + modified_at = models.DateTimeField(auto_now=True) + # image = models.ImageField(upload_to='images/%y/%m/%d', blank=True) + + def __str__(self): + return self.title + + def get_last_comment(self): + return self.comment.last() + + def get_comments_count(self): + return self.comment.count() + +############################################################################## +class Comment(models.Model): + uid = models.UUIDField(unique=True, default=uuid.uuid4, editable=False) + user = models.ForeignKey(User, on_delete=models.CASCADE) + thread = models.ForeignKey(Thread, + on_delete=models.CASCADE, + related_name='comment') + body = models.TextField() + created_at = models.DateTimeField(auto_now_add=True) + modified_at = models.DateTimeField(auto_now=True) + active = models.BooleanField(default=True) #make it false if improper comment + # image = models.ImageField(upload_to='images/%y/%m/%d', blank=True) + + + def __str__(self): + return 'Comment by {0}: \n {1}'.format(self.user.username, + self.thread.title) -- cgit From 0e6c7d589114450d5cd1bc581ee1692c235f1a73 Mon Sep 17 00:00:00 2001 From: CruiseDevice Date: Mon, 13 Apr 2020 16:45:42 +0530 Subject: Add feature for uploading images --- yaksh/models.py | 46 ++++++++++++++++++++++++++++------------------ 1 file changed, 28 insertions(+), 18 deletions(-) (limited to 'yaksh/models.py') diff --git a/yaksh/models.py b/yaksh/models.py index 83c644a..f9878e4 100644 --- a/yaksh/models.py +++ b/yaksh/models.py @@ -11,6 +11,7 @@ from collections import Counter, defaultdict from django.db import models from django.contrib.auth.models import User, Group, Permission +from django.core.exceptions import ValidationError from django.contrib.contenttypes.models import ContentType from taggit.managers import TaggableManager from django.utils import timezone @@ -233,6 +234,18 @@ def render_template(template_path, data=None): return render +def validate_image(image): + file_size = image.file.size + limit_mb = 30 + if file_size > limit_mb * 1024 * 1024: + raise ValidationError("Max size of file is {0} MB".format(limit_mb)) + + +def get_image_dir(instance, filename): + return os.sep.join(( + 'thread_%s' % (instance), filename + )) + ############################################################################### class CourseManager(models.Manager): @@ -2634,16 +2647,21 @@ class TestCaseOrder(models.Model): order = models.TextField() ############################################################################## -class Thread(models.Model): +class ForumBase(models.Model): uid = models.UUIDField(unique=True, default=uuid.uuid4, editable=False) creator = models.ForeignKey(User, on_delete=models.CASCADE) - title = models.CharField(max_length=200) description = models.TextField() - course = models.ForeignKey(Course, - on_delete=models.CASCADE, related_name='thread') created_at = models.DateTimeField(auto_now_add=True) modified_at = models.DateTimeField(auto_now=True) - # image = models.ImageField(upload_to='images/%y/%m/%d', blank=True) + image = models.ImageField(upload_to=get_image_dir, blank=True, + null=True, validators=[validate_image]) + active = models.BooleanField(default=True) + + +class Thread(ForumBase): + title = models.CharField(max_length=200) + course = models.ForeignKey(Course, + on_delete=models.CASCADE, related_name='thread') def __str__(self): return self.title @@ -2654,20 +2672,12 @@ class Thread(models.Model): def get_comments_count(self): return self.comment.count() -############################################################################## -class Comment(models.Model): - uid = models.UUIDField(unique=True, default=uuid.uuid4, editable=False) - user = models.ForeignKey(User, on_delete=models.CASCADE) - thread = models.ForeignKey(Thread, + +class Comment(ForumBase): + thread_field = models.ForeignKey(Thread, on_delete=models.CASCADE, related_name='comment') - body = models.TextField() - created_at = models.DateTimeField(auto_now_add=True) - modified_at = models.DateTimeField(auto_now=True) - active = models.BooleanField(default=True) #make it false if improper comment - # image = models.ImageField(upload_to='images/%y/%m/%d', blank=True) - def __str__(self): - return 'Comment by {0}: \n {1}'.format(self.user.username, - self.thread.title) + return 'Comment by {0}: {1}'.format(self.creator.username, + self.thread_field.title) -- cgit From 2f9331717075b34534f2745706f57a98f7dce20d Mon Sep 17 00:00:00 2001 From: CruiseDevice Date: Mon, 13 Apr 2020 17:27:49 +0530 Subject: Add feature to hide thread or comments --- yaksh/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'yaksh/models.py') diff --git a/yaksh/models.py b/yaksh/models.py index f9878e4..d76d6aa 100644 --- a/yaksh/models.py +++ b/yaksh/models.py @@ -2670,7 +2670,7 @@ class Thread(ForumBase): return self.comment.last() def get_comments_count(self): - return self.comment.count() + return self.comment.filter(active=True).count() class Comment(ForumBase): -- cgit From 508e0e78bb0bd3e8ebbad81e948f13de5c01b20f Mon Sep 17 00:00:00 2001 From: CruiseDevice Date: Tue, 14 Apr 2020 20:13:52 +0530 Subject: Change model name Thread to Post to avoid conflicts - Thread class from threading conflicts with the forum Thread model. - Tests for models and views. - PEP8 fix. --- yaksh/models.py | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) (limited to 'yaksh/models.py') diff --git a/yaksh/models.py b/yaksh/models.py index d76d6aa..424e2f5 100644 --- a/yaksh/models.py +++ b/yaksh/models.py @@ -243,9 +243,10 @@ def validate_image(image): def get_image_dir(instance, filename): return os.sep.join(( - 'thread_%s' % (instance), filename + 'post_%s' % (instance), filename )) + ############################################################################### class CourseManager(models.Manager): @@ -1176,7 +1177,9 @@ class CourseStatus(models.Model): if self.is_course_complete(): self.calculate_percentage() if self.course.grading_system is None: - grading_system = GradingSystem.objects.get(name__contains='default') + grading_system = GradingSystem.objects.get( + name__contains='default' + ) else: grading_system = self.course.grading_system grade = grading_system.get_grade(self.percentage) @@ -2646,6 +2649,7 @@ class TestCaseOrder(models.Model): # Order of the test case for a question. order = models.TextField() + ############################################################################## class ForumBase(models.Model): uid = models.UUIDField(unique=True, default=uuid.uuid4, editable=False) @@ -2653,15 +2657,15 @@ class ForumBase(models.Model): description = models.TextField() created_at = models.DateTimeField(auto_now_add=True) modified_at = models.DateTimeField(auto_now=True) - image = models.ImageField(upload_to=get_image_dir, blank=True, + image = models.ImageField(upload_to=get_image_dir, blank=True, null=True, validators=[validate_image]) active = models.BooleanField(default=True) -class Thread(ForumBase): +class Post(ForumBase): title = models.CharField(max_length=200) course = models.ForeignKey(Course, - on_delete=models.CASCADE, related_name='thread') + on_delete=models.CASCADE, related_name='post') def __str__(self): return self.title @@ -2674,10 +2678,9 @@ class Thread(ForumBase): class Comment(ForumBase): - thread_field = models.ForeignKey(Thread, - on_delete=models.CASCADE, - related_name='comment') + post_field = models.ForeignKey(Post, on_delete=models.CASCADE, + related_name='comment') def __str__(self): return 'Comment by {0}: {1}'.format(self.creator.username, - self.thread_field.title) + self.post_field.title) -- cgit From 169228186d8c9ad880ee33c5190e49203d2c5243 Mon Sep 17 00:00:00 2001 From: CruiseDevice Date: Wed, 15 Apr 2020 21:19:09 +0530 Subject: Resolve comments - Fix "'image' attribute has no file associated with it" issue. - Don't allow users who are not part of a course to see the discussion forum of that course. - Add Discussion forum link in moderator interface under course_details page. - Remove custom css for post and comments in Discussion forum. Use bootstrap 'img-fluid' class instead. 'img-fluid' fills the height and width of the card. - Use instance.uid instead of just instance in get_image_dir. --- yaksh/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'yaksh/models.py') diff --git a/yaksh/models.py b/yaksh/models.py index 424e2f5..4a7c4ba 100644 --- a/yaksh/models.py +++ b/yaksh/models.py @@ -243,7 +243,7 @@ def validate_image(image): def get_image_dir(instance, filename): return os.sep.join(( - 'post_%s' % (instance), filename + 'post_%s' % (instance.uid), filename )) -- cgit