summaryrefslogtreecommitdiff
path: root/yaksh
diff options
context:
space:
mode:
Diffstat (limited to 'yaksh')
-rw-r--r--yaksh/admin.py4
-rw-r--r--yaksh/models.py38
-rw-r--r--yaksh/templates/yaksh/course_forum.html68
-rw-r--r--yaksh/templates/yaksh/course_modules.html1
-rw-r--r--yaksh/templates/yaksh/thread_comments.html46
-rw-r--r--yaksh/urls.py2
-rw-r--r--yaksh/views.py45
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">&times;</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