diff options
Diffstat (limited to 'yaksh')
-rw-r--r-- | yaksh/admin.py | 4 | ||||
-rw-r--r-- | yaksh/models.py | 38 | ||||
-rw-r--r-- | yaksh/templates/yaksh/course_forum.html | 68 | ||||
-rw-r--r-- | yaksh/templates/yaksh/course_modules.html | 1 | ||||
-rw-r--r-- | yaksh/templates/yaksh/thread_comments.html | 46 | ||||
-rw-r--r-- | yaksh/urls.py | 2 | ||||
-rw-r--r-- | yaksh/views.py | 45 |
7 files changed, 201 insertions, 3 deletions
diff --git a/yaksh/admin.py b/yaksh/admin.py index 9c36a98..4489ffc 100644 --- a/yaksh/admin.py +++ b/yaksh/admin.py @@ -1,7 +1,7 @@ from yaksh.models import Question, Quiz, QuestionPaper, Profile from yaksh.models import (TestCase, StandardTestCase, StdIOBasedTestCase, Course, AnswerPaper, CourseStatus, LearningModule, - Lesson + Lesson, Thread, Comment ) from django.contrib import admin @@ -48,6 +48,8 @@ class QuizAdmin(admin.ModelAdmin): admin.site.register(Profile, ProfileAdmin) admin.site.register(Question) admin.site.register(TestCase) +admin.site.register(Thread) +admin.site.register(Comment) admin.site.register(StandardTestCase) admin.site.register(StdIOBasedTestCase) admin.site.register(Course, CourseAdmin) 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) diff --git a/yaksh/templates/yaksh/course_forum.html b/yaksh/templates/yaksh/course_forum.html new file mode 100644 index 0000000..b0c7024 --- /dev/null +++ b/yaksh/templates/yaksh/course_forum.html @@ -0,0 +1,68 @@ +{% extends "user.html" %} +{% load humanize %} +{% block title %} + {{course.name}}: Discussion Forum +{% endblock title %} +{% block content %} + <div class="container"> + <div> + <h2><center>{{course.name}}</center></h2> + <center>Discussion Forum</center> + </div> + <div class="pull-right"> + <button type="button" class="btn btn-primary" data-toggle="modal" data-target="#newThreadModal">New Thread</button> + </div> + <!-- Modal --> + <div id="newThreadModal" class="modal fade" role="dialog"> + <div class="modal-dialog"> + + <!-- Modal content--> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title">Create a new thread</h4> + <button type="button" class="close" data-dismiss="modal">×</button> + </div> + <div class="modal-body"> + <form action="." method="POST"> + <div class="form-group"> + {% csrf_token %} + <label>Title: </label> + <input name='title' type="text" class="form-control" required> + <label>Description: </label> + <textarea class="form-control" name="description" id="" cols="45" rows="3" required></textarea> + </div> + <input type="submit" class="btn btn-primary" value="Create Thread"> + </form> + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default" data-dismiss="modal">Close</button> + </div> + </div> + + </div> + </div> + <br> + <br> + <div> + <h3>Threads:</h3> + {% if threads %} + {% for thread in threads %} + <div class="card"> + <div class="card-body"> + <a href="{% url "yaksh:thread_comments" course.id thread.uid %}">{{thread.title}}</a> + <p class="pull-right"><small>{{thread.get_comments_count}}{% if thread.get_comments_count > 1 %} replies{% else %} reply{% endif %}</small></p> + </div> + <div class="card-footer"> + {% with thread.get_last_comment as last_comment %} + <small> {% if thread.creator.profile.is_moderator %} INSTRUCTOR CREATED {% endif %} Last Post by: <strong>{{last_comment.user}}</strong> . {{last_comment.modified_at|naturaltime}}</small> + {% endwith %} + </div> + </div> + <br> + {% endfor %} + {% else %} + No discussion threads are there yet. Create one to start discussing. + {% endif %} + </div> + </div> +{% endblock content %}
\ No newline at end of file diff --git a/yaksh/templates/yaksh/course_modules.html b/yaksh/templates/yaksh/course_modules.html index dd7b68d..b808562 100644 --- a/yaksh/templates/yaksh/course_modules.html +++ b/yaksh/templates/yaksh/course_modules.html @@ -7,6 +7,7 @@ <div class="card"> <div class="card-header"> {{ course.name }} + <a href="{% url "yaksh:course_forum" course.id %}" class="btn btn-info pull-right">Discussion Forum</a> </div> <div class="card-body"> {% if course.view_grade %} diff --git a/yaksh/templates/yaksh/thread_comments.html b/yaksh/templates/yaksh/thread_comments.html new file mode 100644 index 0000000..245c363 --- /dev/null +++ b/yaksh/templates/yaksh/thread_comments.html @@ -0,0 +1,46 @@ +{% extends "user.html" %} + +{% block title %} + {{thread.title}} +{% endblock title %} + +{% block content %} + <div class="container"> + <a class="btn btn-primary" href="{% url "yaksh:course_forum" thread.course.id %}">Back to Threads</a> + <div class="card"> + <div class="card-header"> + {{thread.title}} + <br> + <small><strong>{{thread.creator.username}}</strong> {{thread.created_at}}</small> + </div> + <div class="card-body"> + <p>{{thread.description}}</p> + </div> + </div> + <br> + <div class="card"> + {% if comments %} + <div class="card-header">Comments:</div> + {% for comment in comments %} + <div class="card-body"> + <p>{{comment.body}}</p> + <small class="pull-right">by: <strong>{{comment.user.username}} </strong>. {{comment.created_at}}</small> + </div> + <hr> + {% endfor %} + {% else %} + No comments on this thread. + {% endif %} + </div> + <br> + <div> + <form action="{% url "yaksh:thread_comments" thread.course.id thread.uid %}" method="POST"> + <div class="form-group"> + {% csrf_token %} + <textarea class="form-control" name="comment" id="" cols="55" rows="5" required></textarea> + </div> + <input type="submit" value="Submit" class="btn btn-primary"> + </form> + </div> + </div> +{% endblock content %}
\ No newline at end of file diff --git a/yaksh/urls.py b/yaksh/urls.py index bdc3330..47cfad4 100644 --- a/yaksh/urls.py +++ b/yaksh/urls.py @@ -59,6 +59,8 @@ urlpatterns = [ views.get_next_unit, name='next_unit'), url(r'^course_modules/(?P<course_id>\d+)/$', views.course_modules, name='course_modules'), + url(r'^forum/(?P<course_id>\d+)/$', views.course_forum, name='course_forum'), + url(r'^forum/(?P<course_id>\d+)/thread/(?P<uuid>[0-9a-f-]+)/', views.thread_comments, name='thread_comments'), url(r'^manage/$', views.prof_manage, name='manage'), url(r'^manage/addquestion/$', views.add_question, name="add_question"), url(r'^manage/addquestion/(?P<question_id>\d+)/$', views.add_question, diff --git a/yaksh/views.py b/yaksh/views.py index 9efcbe9..9350f0a 100644 --- a/yaksh/views.py +++ b/yaksh/views.py @@ -1,6 +1,6 @@ import os import csv -from django.http import HttpResponse, JsonResponse +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 @@ -37,7 +37,7 @@ 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 + LearningUnit, LearningModule, CourseStatus, question_types, Thread, Comment ) from yaksh.forms import ( UserRegisterForm, UserLoginForm, QuizForm, QuestionForm, @@ -3191,3 +3191,44 @@ def download_course_progress(request, course_id): for student in stud_details: writer.writerow(student) return response + + +def course_forum(request, course_id): + user = request.user + course = get_object_or_404(Course, id=course_id) + threads = course.thread.all().order_by('modified_at') + if request.method == "POST": + title = request.POST['title'] + description = request.POST['description'] + if title and description: + new_thread = Thread.objects.create(title=title, + description=description, + creator=user, course=course) + new_thread.save() + return render(request, 'yaksh/thread_comments.html', { + 'thread': new_thread, + 'course': course, + 'user': user, + }) + return render(request, 'yaksh/course_forum.html', { + 'user': user, + 'course': course, + 'threads': threads + }) + + +def thread_comments(request, course_id, uuid): + thread = get_object_or_404(Thread, uid=uuid) + comments = thread.comment.filter(active=True) + if request.method == "POST": + comment = request.POST.get('comment') + if comment is not None: + new_comment = Comment.objects.create(thread=thread, + body=comment, + user=request.user) + new_comment.save() + return HttpResponseRedirect(request.path_info) + return render(request, 'yaksh/thread_comments.html', { + 'thread': thread, + 'comments': comments + })
\ No newline at end of file |