summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--static/forums/templates/user-login.html43
-rw-r--r--static/website/css/main.css42
-rw-r--r--static/website/js/thread-user.js32
-rw-r--r--static/website/templates/base.html14
-rw-r--r--static/website/templates/get-question.html23
-rw-r--r--static/website/templates/index.html30
-rw-r--r--static/website/templates/notifications.html33
-rw-r--r--static/website/templates/notify.html7
-rw-r--r--static/website/templates/user-questions.html36
-rw-r--r--static/website/templates/user-replies.html36
-rw-r--r--website/models.py7
-rw-r--r--website/templatetags/notify.py23
-rw-r--r--website/urls.py6
-rw-r--r--website/views.py94
14 files changed, 385 insertions, 41 deletions
diff --git a/static/forums/templates/user-login.html b/static/forums/templates/user-login.html
index 6ac4fee..27f5a1f 100644
--- a/static/forums/templates/user-login.html
+++ b/static/forums/templates/user-login.html
@@ -1,4 +1,39 @@
-<form action="/accounts/login/" method="POST"> {% csrf_token %}
- {{ form.as_p }}
- <input type="submit" value="Login">
-</form>
+{% extends "website/templates/base.html" %}
+{% load widget_tweaks %}
+{% block content %}
+<br><br><br>
+<div class="row">
+ <div class="col-lg-6" style="border-right: 1px dashed #424242;">
+ <h4>Please login with your <br>Spoken-Tutorial.org account.</h4>
+ <form action="/accounts/login/" method="POST"> {% csrf_token %}
+ {% with WIDGET_ERROR_CLASS='field_error' %}
+ <div class="form-group">
+ <label for="id_username">Username:</label>
+ {% render_field form.username class+="form-control" %}
+ </div>
+
+ <div class="form-group">
+ <label for="id_username">Password:</label>
+ {% render_field form.password class+="form-control" %}
+ </div>
+
+ <input class="btn btn-sm btn-primary" type="submit" value="Login">
+ {% endwith %}
+ </form>
+ </div> <!-- /.col -->
+
+ <div class="col-lg-6">
+ <h4>Rules and Regulations</h4>
+ <ul>
+ <li>This forum is a place to discuss questions and doubts related to the Spoken-Tutorial's</li>
+ <li>Please restrain yourself from using abusive language.</li>
+ <li>This is not a place for self promotion.</li>
+ <li>Any violation of the above may lead to the permanent account deletion.</li>
+ </ul>
+ <h4>Dont have a Spoken-Tutorial.org account yet ?</h4>
+ <p>
+ <a class="btn btn-sm btn-success" href="#">Register</a>
+ </p>
+ </div> <!-- /.col -->
+</div> <!-- /.row -->
+{% endblock %}
diff --git a/static/website/css/main.css b/static/website/css/main.css
index 7a58a4c..a5f8c81 100644
--- a/static/website/css/main.css
+++ b/static/website/css/main.css
@@ -1,3 +1,8 @@
+/* override bootstrap */
+.navbar>.container .navbar-brand {
+ margin-left: 0;
+}
+/* main styles */
.container {
max-width: 970px;
}
@@ -22,7 +27,7 @@
}
#content .editable {
padding: 15px 5px 15px 5px;
- background: lightyellow;
+ background: #F0F0F0;
}
#content .question .title a{
padding: 0 0 7px 0;
@@ -60,12 +65,14 @@
background: #f5f5f5;
color: #424242;
}
-#content .question .user {
+#content .question .meta{
position: absolute;
right: 0px;
bottom: 0px;
- padding: 2px 7px;
+}
+#content .question .user{
background: #f5f5f5;
+ padding: 2px 7px;
}
#similar-link {
display: none;
@@ -92,7 +99,8 @@
#content .reply {
position: relative;
border-bottom: 1px solid #f5f5f5;
- padding: 20px 0;
+ padding-top: 20px;
+ padding-bottom: 20px;
margin: 10px 0px;
}
#content .reply .body {
@@ -114,3 +122,29 @@
.field_error {
border: 1px solid red;
}
+.notification {
+ position: relative;
+ padding: 15px;
+ margin: 10px 0;
+ border-left: 2px solid #424242;
+ background: #f7f7f7;
+}
+.notification .remove {
+ position: absolute;
+ right: 10px;
+ top: 15px;
+}
+.my-question,
+.my-reply {
+ position: relative;
+ margin: 10px auto;
+ padding: 15px;
+ border-left: 2px solid #424242;
+ background: #f7f7f7;
+}
+.my-question .date,
+.my-reply .date {
+ position: absolute;
+ right: 5px;
+ bottom: 5px;
+}
diff --git a/static/website/js/thread-user.js b/static/website/js/thread-user.js
index 698a946..a8e7eee 100644
--- a/static/website/js/thread-user.js
+++ b/static/website/js/thread-user.js
@@ -21,7 +21,7 @@ $(document).ready(function() {
$questionInstance = $("#questionInstance");
/* make the question editable and show modify */
- $question.addClass("editable");
+ //$question.addClass("editable");
$question_modify.show();
/* edit and save click events */
@@ -43,8 +43,9 @@ $(document).ready(function() {
$(this).prev().css("display", "block");
/* make the ajax call */
- var id_length = $question_save.attr("id").length;
- var question_id = parseInt($question_save.attr("id").substr(id_length-1));
+ //var id_length = $question_save.attr("id").length;
+ //var question_id = parseInt($question_save.attr("id").substr(id_length-1));
+ var question_id = parseInt($question_save.data("qid"));
console.log(question_id);
var question_body = $questionInstance.html();
$.ajax({
@@ -76,9 +77,9 @@ $(document).ready(function() {
replyNicEditor.panelInstance('replyNicPanel');
$reply_edit.click(function() {
- var reply_body = $(this).data("target");
- console.log(reply_body);
- replyNicEditor.addInstance(reply_body);
+ var target = $(this).data("target");
+ console.log(target);
+ replyNicEditor.addInstance(target);
$(this).parents("div.reply").prepend($replyPanelWrapper);
$replyPanelWrapper.show();
$('#replyPanelWrapper .nicEdit-panelContain').parent().width('100%');
@@ -88,12 +89,27 @@ $(document).ready(function() {
});
$reply_save.click(function() {
- var reply_body = $(this).data("target");
- replyNicEditor.removeInstance(reply_body);
+ var target = $(this).data("target");
+ replyNicEditor.removeInstance(target);
$replyPanelWrapper.hide();
$('#replyPanelWrapper .nicEdit-panelContain').parent().width('100%');
$(this).hide();
$(this).prev().show();
+
+ var reply_id = parseInt($(this).data("rid"));
+ var reply_body = $("#"+target).html();
+
+ $.ajax({
+ url: "/ajax-reply-update/",
+ type: "POST",
+ data: {
+ reply_id: reply_id,
+ reply_body: reply_body
+ },
+ success: function(data) {
+ console.log(data);
+ }
+ });
});
});
diff --git a/static/website/templates/base.html b/static/website/templates/base.html
index 5e397e8..c71e3ef 100644
--- a/static/website/templates/base.html
+++ b/static/website/templates/base.html
@@ -39,9 +39,17 @@
{{ user }}<b class="caret"></b>
</a>
<ul class="dropdown-menu">
- <li><a href="#">My Questions</a></li>
- <li><a href="#">My Replies</a></li>
- <li><a href="#">Notifications</a></li>
+ <li><a href="{% url 'website:user_questions' user.id %}">My Questions</a></li>
+ <li><a href="{% url 'website:user_replies' user.id %}">My Replies</a></li>
+ <li>
+ <a href="{% url 'website:user_notifications' user.id %}">
+ Notifications
+ <span class="badge" style="background:#a26dc8; color:#ffffff;">
+ {% load notify %}
+ {% notification_count user.id %}
+ </span>
+ </a>
+ </li>
<li class="divider"></li>
<li><a href="{% url 'user_logout' %}">Logout</a></li>
</ul>
diff --git a/static/website/templates/get-question.html b/static/website/templates/get-question.html
index 5e68aed..bd63d02 100644
--- a/static/website/templates/get-question.html
+++ b/static/website/templates/get-question.html
@@ -2,13 +2,13 @@
{% load static %}
{% load widget_tweaks %}
{% block content %}
-<div class="question">
+<div class="question {% ifequal question.user|stringformat:'s' user|stringformat:'s' %}editable{% endifequal %}">
<div class="title">
<a href=""> {{ question.title }} </a>
</div>
<div id="questionNicPanel"></div>
- <div id="questionInstance" class="body">
+ <div id="{% ifequal question.user|stringformat:'s' user|stringformat:'s' %}questionInstance{% endifequal %}" class="body">
{{ question.body|safe }}
</div>
<br>
@@ -48,7 +48,7 @@
<span class="modify">
{% ifequal question.uid|stringformat:'s' user.id|stringformat:'s' %}
<a class="edit btn btn-xs btn-info" href="#">Edit</a>
- <a id="save-{{ question.id }}" class="save btn btn-xs btn-success" href="#">Save</a>
+ <a class="save btn btn-xs btn-success" data-qid="{{ question.id }}" href="#">Save</a>
{% endifequal %}
</span>
@@ -65,7 +65,7 @@
</div>
{% for reply in replies %}
- <div class="reply {% ifequal reply.uid|stringformat:'s' user.id|stringformat:'s' %}editable{% endifequal %}">
+ <div class="reply {% ifequal reply.uid|stringformat:'s' user.id|stringformat:'s' %}editable{% endifequal %}" id="reply{{reply.id}}">
<div class="body" id="body{{ reply.id }}">
{{ reply.body|safe }}
@@ -78,7 +78,7 @@
{% ifequal reply.uid|stringformat:'s' user.id|stringformat:'s' %}
<span class="modify" style="display:block">
<a class="edit btn btn-xs btn-info vs" href="#body{{ reply.id}}" data-target="body{{ reply.id }}">Edit</a>
- <a id="save-{{ question.id }}" class="save btn btn-xs btn-success vs" href="#" data-target="body{{ reply.id }}">Save</a>
+ <a class="save btn btn-xs btn-success vs" data-target="body{{ reply.id }}" data-rid="{{ reply.id }}" href="#">Save</a>
</span>
{% endifequal %}
</div> <!-- /.reply -->
@@ -111,16 +111,5 @@
{% endblock %}
{% block javascript %}
- {% if user.is_authenticated %}
- {% ifequal question.user|stringformat:"s" user|stringformat:"s" %}
- <script src="{% static 'website/js/thread-user.js' %}"></script>
- {% else %}
- <script src="{% static 'website/js/thread-user.js' %}"></script>
- <script type="text/javascript">
- $(document).ready(function() {
- $(".question .body").removeAttr("id");
- });
- </script>
- {% endifequal %}
- {% endif %}
+ <script src="{% static 'website/js/thread-user.js' %}"></script>
{% endblock %}
diff --git a/static/website/templates/index.html b/static/website/templates/index.html
index 43d98f0..ef840bc 100644
--- a/static/website/templates/index.html
+++ b/static/website/templates/index.html
@@ -1,5 +1,6 @@
{% extends 'website/templates/base.html' %}
{% block content %}
+{% load count_tags %}
<h4><u>Recent Questions</u></h4>
{% for question in questions %}
<div class="question">
@@ -39,9 +40,34 @@
</small>
</span>
- <span class="user">
- {{ question.user }}
+ <span class="meta">
+ <small>
+ <i>
+ {{ question.date_created }}
+ </i>
+ </small>
+
+ <span class="user">
+ {{ question.user }}
+ </span>
</span>
</div> <!-- /.question -->
{% endfor %}
+
+ {% if total > 10 %}
+ <ul class="pagination pull-right">
+ {% for i in total|get_range:"0,10" %}
+ <li>
+ <a href="{% url 'website:home' %}?marker={{ i }}">
+ {% if i == marker %}
+ <strong>{{ i|div:"10"|inc }}</strong>
+ {% else %}
+ {{ i|div:"10"|inc }}
+ {% endif %}
+ </a>
+ </li>
+ {% endfor %}
+ </ul>
+ {% endif %}
+
{% endblock %}
diff --git a/static/website/templates/notifications.html b/static/website/templates/notifications.html
new file mode 100644
index 0000000..aa3adce
--- /dev/null
+++ b/static/website/templates/notifications.html
@@ -0,0 +1,33 @@
+{% extends 'website/templates/base.html' %}
+{% load notify %}
+{% block content%}
+ <h4 class="pull-left">Notifications</h4>
+ <a class="btn btn-xs btn-warning pull-right" href="{% url "website:clear_notifications" %}" style="margin-top: 7px;">
+ Clear All
+ </a>
+ <div class="clearfix"></div>
+ {% for notification in notifications %}
+ {% get_notification notification.id %}
+ {% endfor %}
+{% endblock %}
+
+{% block javascript %}
+ <script type="text/javascript">
+ $(document).ready(function() {
+ $(".remove").click(function() {
+ $(this).parent(".notification").slideUp();
+ var notification_id = $(this).data("nid");
+ $.ajax({
+ url: "/ajax-notification-remove/",
+ type: "POST",
+ data: {
+ notification_id: notification_id
+ },
+ success: function(data) {
+ console.log(data);
+ }
+ });
+ });
+ });
+ </script>
+{% endblock %}
diff --git a/static/website/templates/notify.html b/static/website/templates/notify.html
new file mode 100644
index 0000000..7251f1b
--- /dev/null
+++ b/static/website/templates/notify.html
@@ -0,0 +1,7 @@
+<div class="notification">
+ <a href=""><strong>{{ reply.user }}</strong> replies to <strong>{{ question.title }}</strong></a> /
+ {{ reply.body|safe }}
+ <a class="remove" data-nid="{{ notification.id }}" href="#">
+ <span class="glyphicon glyphicon-remove-circle"></span>
+ </a>
+</div> <!-- /.notification -->
diff --git a/static/website/templates/user-questions.html b/static/website/templates/user-questions.html
new file mode 100644
index 0000000..e3d2ab6
--- /dev/null
+++ b/static/website/templates/user-questions.html
@@ -0,0 +1,36 @@
+{% extends 'website/templates/base.html' %}
+{% load count_tags %}
+{% block content %}
+ <h4>My Questions</h4>
+ {% for question in questions %}
+ <div class="my-question">
+ <span class="title">
+ {{ question.title }}
+ </span>
+ <br>
+ <span class="date">
+ <small>
+ Asked on:
+ {{ question.date_created }}
+ </small>
+ </span>
+ </div>
+ {% endfor %}
+
+ {% if total > 10 %}
+ <ul class="pagination pull-right">
+ {% for i in total|get_range:"0,10" %}
+ <li>
+ <a href="{% url 'website:user_questions' user.id %}?marker={{ i }}">
+ {% if i == marker %}
+ <strong>{{ i|div:"10"|inc }}</strong>
+ {% else %}
+ {{ i|div:"10"|inc }}
+ {% endif %}
+ </a>
+ </li>
+ {% endfor %}
+ </ul>
+ {% endif %}
+
+{% endblock %}
diff --git a/static/website/templates/user-replies.html b/static/website/templates/user-replies.html
new file mode 100644
index 0000000..c31b854
--- /dev/null
+++ b/static/website/templates/user-replies.html
@@ -0,0 +1,36 @@
+{% extends 'website/templates/base.html' %}
+{% load count_tags %}
+{% block content %}
+ <h4>My Replies</h4>
+ {% for reply in replies%}
+ <div class="my-reply">
+ <span class="body">
+ {{ reply.body|safe }}
+ </span>
+ <br>
+ <span class="date">
+ <small>
+ Replied on:
+ {{ reply.date_created }}
+ </small>
+ </span>
+ </div>
+ {% endfor %}
+
+ {% if total > 10 %}
+ <ul class="pagination pull-right">
+ {% for i in total|get_range:"0,10" %}
+ <li>
+ <a href="{% url 'website:user_replies' user.id %}?marker={{ i }}">
+ {% if i == marker %}
+ <strong>{{ i|div:"10"|inc }}</strong>
+ {% else %}
+ {{ i|div:"10"|inc }}
+ {% endif %}
+ </a>
+ </li>
+ {% endfor %}
+ </ul>
+ {% endif %}
+
+{% endblock %}
diff --git a/website/models.py b/website/models.py
index 22a1fe8..52575b8 100644
--- a/website/models.py
+++ b/website/models.py
@@ -33,6 +33,13 @@ class Reply(models.Model):
user = User.objects.get(id=self.uid)
return user.username
+class Notification(models.Model):
+ uid = models.IntegerField()
+ pid = models.IntegerField()
+ qid = models.IntegerField()
+ rid = models.IntegerField()
+ date_created = models.DateTimeField(auto_now_add=True)
+
# CDEEP database created using inspectdb arg of manage.py
class TutorialDetails(models.Model):
id = models.IntegerField(primary_key=True)
diff --git a/website/templatetags/notify.py b/website/templatetags/notify.py
new file mode 100644
index 0000000..4c6692a
--- /dev/null
+++ b/website/templatetags/notify.py
@@ -0,0 +1,23 @@
+from django import template
+
+from website.models import Question, Reply, Notification
+
+register = template.Library()
+
+def get_notification(nid):
+ notification = Notification.objects.get(pk=nid)
+ question = Question.objects.get(pk=notification.qid);
+ reply = Reply.objects.get(pk=notification.rid)
+ context = {
+ 'notification': notification,
+ 'question': question,
+ 'reply': reply,
+ }
+ return context
+register.inclusion_tag('website/templates/notify.html')(get_notification)
+
+def notification_count(user_id):
+ count = Notification.objects.filter(uid=user_id).count()
+ return count
+register.simple_tag(notification_count)
+
diff --git a/website/urls.py b/website/urls.py
index c385ea0..20f8201 100644
--- a/website/urls.py
+++ b/website/urls.py
@@ -9,10 +9,16 @@ urlpatterns = patterns('',
url(r'^filter/(?P<category>[^/]+)/(?P<tutorial>[^/]+)/(?P<minute_range>[^/]+)/$', 'website.views.filter', name='filter'),
url(r'^filter/(?P<category>[^/]+)/(?P<tutorial>[^/]+)/(?P<minute_range>[^/]+)/(?P<second_range>[^/]+)/$', 'website.views.filter', name='filter'),
url(r'^new-question/$', 'website.views.new_question', name='new_question'),
+ url(r'^user/(?P<user_id>\d+)/notifications/$', 'website.views.user_notifications', name='user_notifications'),
+ url(r'^user/(?P<user_id>\d+)/questions/$', 'website.views.user_questions', name='user_questions'),
+ url(r'^user/(?P<user_id>\d+)/replies/$', 'website.views.user_replies', name='user_replies'),
+ url(r'^clear-notifications/$', 'website.views.clear_notifications', name='clear_notifications'),
# Ajax helpers
url(r'^ajax-tutorials/$', 'website.views.ajax_tutorials', name='ajax_tutorials'),
url(r'^ajax-duration/$', 'website.views.ajax_duration', name='ajax_duration'),
url(r'^ajax-question-update/$', 'website.views.ajax_question_update', name='ajax_question_update'),
+ url(r'^ajax-reply-update/$', 'website.views.ajax_reply_update', name='ajax_reply_update'),
url(r'^ajax-similar-questions/$', 'website.views.ajax_similar_questions', name='ajax_similar_questions'),
+ url(r'^ajax-notification-remove/$', 'website.views.ajax_notification_remove', name='ajax_notification_remove'),
)
diff --git a/website/views.py b/website/views.py
index 538d90e..b6c6670 100644
--- a/website/views.py
+++ b/website/views.py
@@ -5,7 +5,7 @@ from django.views.decorators.csrf import csrf_exempt
from django.contrib.auth.decorators import login_required
from django.db.models import Q
-from website.models import Question, Reply, TutorialDetails, TutorialResources
+from website.models import Question, Reply, Notification, TutorialDetails, TutorialResources
from website.forms import NewQuestionForm, ReplyQuesitionForm
from website.helpers import get_video_info
@@ -28,10 +28,17 @@ categories = [
]
def home(request):
- questions = Question.objects.all().order_by('date_created').reverse()[:10]
+ marker = 0
+ if 'marker' in request.GET:
+ marker = int(request.GET['marker'])
+
+ total = Question.objects.all().count()
+ total = int(total - (total % 10 - 10))
+ questions = Question.objects.all().order_by('date_created').reverse()[marker:marker+10]
context = {
'questions': questions,
- 'user': request.user
+ 'total': total,
+ 'marker': marker
}
return render(request, 'website/templates/index.html', context)
@@ -64,6 +71,13 @@ def question_reply(request):
reply.question = question
reply.body = body
reply.save()
+ if question.uid != request.user.id:
+ notification = Notification()
+ notification.uid = question.uid
+ notification.pid = request.user.id
+ notification.qid = qid
+ notification.rid = reply.id
+ notification.save()
return HttpResponseRedirect('/question/'+str(qid))
def filter(request, category=None, tutorial=None, minute_range=None, second_range=None):
@@ -112,6 +126,58 @@ def new_question(request):
context.update(csrf(request))
return render(request, 'website/templates/new-question.html', context)
+@login_required
+def user_questions(request, user_id):
+ marker = 0
+ if 'marker' in request.GET:
+ marker = int(request.GET['marker'])
+
+ if str(user_id) == str(request.user.id):
+ total = Question.objects.filter(uid=user_id).count()
+ total = int(total - (total % 10 - 10))
+ questions = Question.objects.filter(uid=user_id).order_by('date_created').reverse()[marker:marker+10]
+
+ context = {
+ 'questions': questions,
+ 'total': total,
+ 'marker': marker
+ }
+ return render(request, 'website/templates/user-questions.html', context)
+ return HttpResponse("go away")
+
+@login_required
+def user_replies(request, user_id):
+ marker = 0
+ if 'marker' in request.GET:
+ marker = int(request.GET['marker'])
+
+ if str(user_id) == str(request.user.id):
+ total = Reply.objects.filter(uid=user_id).count()
+ total = int(total - (total % 10 - 10))
+ replies =Reply.objects.filter(uid=user_id).order_by('date_created').reverse()[marker:marker+10]
+ context = {
+ 'replies': replies,
+ 'total': total,
+ 'marker': marker
+ }
+ return render(request, 'website/templates/user-replies.html', context)
+ return HttpResponse("go away")
+
+@login_required
+def user_notifications(request, user_id):
+ if str(user_id) == str(request.user.id):
+ notifications = Notification.objects.filter(uid=user_id).order_by('date_created').reverse()
+ context = {
+ 'notifications': notifications
+ }
+ return render(request, 'website/templates/notifications.html', context)
+ return HttpResponse("go away ...")
+
+@login_required
+def clear_notifications(request):
+ Notification.objects.filter(uid=request.user.id).delete()
+ return HttpResponseRedirect("/user/{}/notifications/".format(request.user.id))
+
@csrf_exempt
def ajax_tutorials(request):
if request.method == 'POST':
@@ -157,6 +223,18 @@ def ajax_question_update(request):
return HttpResponse("saved")
@csrf_exempt
+def ajax_reply_update(request):
+ if request.method == 'POST':
+ rid = request.POST['reply_id']
+ body = request.POST['reply_body']
+ reply= get_object_or_404(Reply, pk=rid)
+ if reply:
+ if reply.uid == request.user.id:
+ reply.body = body
+ reply.save()
+ return HttpResponse("saved")
+
+@csrf_exempt
def ajax_similar_questions(request):
if request.method == 'POST':
category = request.POST['category']
@@ -171,3 +249,13 @@ def ajax_similar_questions(request):
}
return render(request, 'website/templates/ajax-similar-questions.html', context);
+@csrf_exempt
+def ajax_notification_remove(request):
+ if request.method == "POST":
+ nid = request.POST["notification_id"]
+ notification = Notification.objects.get(pk=nid)
+ if notification:
+ if notification.uid == request.user.id:
+ notification.delete()
+ return HttpResponse("removed")
+ return HttpResponse("failed")