diff options
author | Jayaram Pai | 2013-12-01 13:09:49 +0530 |
---|---|---|
committer | Jayaram Pai | 2013-12-01 13:09:49 +0530 |
commit | 8533d61eb93ecb4c943ec3c3b83dfef87b20a916 (patch) | |
tree | 4fa52f3c02fe1f5c50a4d386cc670faeaae6d7e4 | |
parent | af3e4d8942680a5c08492d2ed179d8e401a8bf57 (diff) | |
download | FOSSEE-Forum-8533d61eb93ecb4c943ec3c3b83dfef87b20a916.tar.gz FOSSEE-Forum-8533d61eb93ecb4c943ec3c3b83dfef87b20a916.tar.bz2 FOSSEE-Forum-8533d61eb93ecb4c943ec3c3b83dfef87b20a916.zip |
basic auth and new-question
25 files changed, 448 insertions, 59 deletions
diff --git a/forums/forms.py b/forums/forms.py new file mode 100644 index 0000000..2e3a6d1 --- /dev/null +++ b/forums/forms.py @@ -0,0 +1,6 @@ +from django import forms + +class UserLoginForm(forms.Form): + username = forms.CharField() + password = forms.CharField(widget=forms.PasswordInput()) + diff --git a/forums/settings.py b/forums/settings.py index 3345be2..37d6202 100644 --- a/forums/settings.py +++ b/forums/settings.py @@ -143,6 +143,7 @@ INSTALLED_APPS = ( # Uncomment the next line to enable admin documentation: # 'django.contrib.admindocs', 'website', + 'widget_tweaks', ) # A sample logging configuration. The only tangible logging diff --git a/forums/urls.py b/forums/urls.py index 1e4ee04..e129d4b 100644 --- a/forums/urls.py +++ b/forums/urls.py @@ -15,4 +15,8 @@ urlpatterns = patterns('', # Uncomment the next line to enable the admin: url(r'^admin/', include(admin.site.urls)), + + # User account urls + url(r'^accounts/login/', 'forums.views.user_login', name='user_login'), + url(r'^accounts/logout/', 'forums.views.user_logout', name='user_logout'), ) diff --git a/forums/views.py b/forums/views.py new file mode 100644 index 0000000..6890d61 --- /dev/null +++ b/forums/views.py @@ -0,0 +1,34 @@ +from django.http import HttpResponse, HttpResponseRedirect +from django.contrib.auth import login, logout, authenticate +from django.shortcuts import render_to_response +from django.core.context_processors import csrf + +from forums.forms import UserLoginForm + +def user_login(request): + if request.user.is_anonymous(): + if request.method == 'POST': + username = request.POST['username'] + password = request.POST['password'] + user = authenticate(username=username, password=password) + if user is not None: + if user.is_active: + login(request, user) + return HttpResponseRedirect('/') + else: + return HttpResponse('you are blocked') + else: + return HttpResponse('Invalid username or password') + else: + form = UserLoginForm() + context = { + 'form': form + } + context.update(csrf(request)) + return render_to_response('forums/templates/user-login.html', context) + else: + return HttpResponseRedirect('/') + +def user_logout(request): + logout(request) + return HttpResponseRedirect('/') diff --git a/static/forums/templates/user-login.html b/static/forums/templates/user-login.html new file mode 100644 index 0000000..6ac4fee --- /dev/null +++ b/static/forums/templates/user-login.html @@ -0,0 +1,4 @@ +<form action="/accounts/login/" method="POST"> {% csrf_token %} + {{ form.as_p }} + <input type="submit" value="Login"> +</form> diff --git a/static/website/css/main.css b/static/website/css/main.css index 997a154..9e68e7f 100644 --- a/static/website/css/main.css +++ b/static/website/css/main.css @@ -10,11 +10,14 @@ #content-inner { } +#content{ + min-height: 600px; +} #content .category { min-height: 50px; border-bottom: 1px solid #f5f5f5; } -#content .category .posts { +#content .category .questions { color: #7395d9; } #content .category .replies { @@ -38,3 +41,6 @@ #footer-inner { } +.field_error { + border: 1px solid red; +} diff --git a/static/website/images/ajax-loader.gif b/static/website/images/ajax-loader.gif Binary files differnew file mode 100644 index 0000000..e192ca8 --- /dev/null +++ b/static/website/images/ajax-loader.gif diff --git a/static/website/js/custom.js b/static/website/js/custom.js new file mode 100644 index 0000000..20801f6 --- /dev/null +++ b/static/website/js/custom.js @@ -0,0 +1,44 @@ +$(document).ready(function() { + $category = $("#id_category"); + $tutorial = $("#id_tutorial"); + $minute_range = $("#id_minute_range"); + $second_range = $("#id_second_range"); + + $category.change(function() { + var category = $(this).val(); + $.ajax({ + url: "/ajax-tutorials/", + type: "POST", + data: { + category: category + }, + success: function(data) { + $("#id_tutorial").html(data); + $("#id_tutorial").removeAttr("disabled"); + console.log("response = " + data); + } + }); + }); + + $tutorial.change(function() { + console.log("tut changed"); + var category = $category.val(); + var tutorial = $(this).val(); + $.ajax({ + url: "/ajax-duration/", + type: "POST", + data: { + category: category, + tutorial: tutorial + }, + success: function(data){ + var $response = $(data); + console.log($response.html()); + $minute_range.html($response.find("#minutes").html()) + $minute_range.removeAttr("disabled"); + $second_range.html($response.find("#seconds").html()) + $second_range.removeAttr("disabled"); + } + }); + }); +}); diff --git a/static/website/templates/ajax-duration.html b/static/website/templates/ajax-duration.html new file mode 100644 index 0000000..f89927b --- /dev/null +++ b/static/website/templates/ajax-duration.html @@ -0,0 +1,16 @@ +{% load count_tags %} +<div> +<div id="minutes"> + <option value="None">min</option> + {% for i in minutes|inc|get_range %} + <option value="{{ i }}-{{ i|inc }}">{{ i }}-{{ i|inc }} </option> + {% endfor %} +</div> <!-- /#minutes --> + +<div id="seconds"> + <option value="None">sec</option> + {% for i in seconds|get_range:"0,10" %} + <option value="{{ i }}">{{ i }}-{{ i|add:"10" }} </option> + {% endfor %} +</div> <!-- /#seconds --> +</div> <!-- /required for ajax --> diff --git a/static/website/templates/ajax-tutorials.html b/static/website/templates/ajax-tutorials.html new file mode 100644 index 0000000..7429f59 --- /dev/null +++ b/static/website/templates/ajax-tutorials.html @@ -0,0 +1,4 @@ +<option value="None">Select a Tutorial</option> +{% for tutorial in tutorials %} + <option value="{{ tutorial.tutorial_name }}">{{ tutorial.tutorial_name }}</option> +{% endfor %} diff --git a/static/website/templates/base.html b/static/website/templates/base.html index dd81da9..f89417f 100644 --- a/static/website/templates/base.html +++ b/static/website/templates/base.html @@ -53,7 +53,7 @@ {% block sidebar %} <h4>Recent Posts</h4> {% load sidebar_tags %} - {% recent_posts %} + {% recent_questions %} {% endblock %} </div> <!-- /#sidebar --> </div> <!-- /#content-inner --> @@ -70,5 +70,6 @@ <script src="{% static 'website/js/jquery.min.js' %}"></script> <script src="{% static 'website/js/bootstrap.min.js' %}"></script> + <script src="{% static 'website/js/custom.js' %}"></script> </body> </html> diff --git a/static/website/templates/fetch_questions.html b/static/website/templates/fetch_questions.html new file mode 100644 index 0000000..d7492fc --- /dev/null +++ b/static/website/templates/fetch_questions.html @@ -0,0 +1,9 @@ +{% extends 'website/templates/base.html' %} +{% block content %} +{{ category }}, {{ tutorial }} +<br> +Number of questions: {{ questions|length }} <br> +{% for question in questions %} + <a href="{% url 'website:get_question' question.id %}"> {{ question.title }}</a> +{% endfor %} +{% endblock %} diff --git a/static/website/templates/fetch_tutorials.html b/static/website/templates/fetch_tutorials.html index a99caec..246c35f 100644 --- a/static/website/templates/fetch_tutorials.html +++ b/static/website/templates/fetch_tutorials.html @@ -2,7 +2,7 @@ {% block content %} {% for tut in tutorials %} <div class="tutorial"> - <a href="{% url 'website:fetch_posts' category tut.tutorial_name %}"> + <a href="{% url 'website:fetch_questions' category tut.tutorial_name %}"> {{tut.tutorial_name}} </a> </div> diff --git a/static/website/templates/get_tutorial.html b/static/website/templates/get_tutorial.html new file mode 100644 index 0000000..159f342 --- /dev/null +++ b/static/website/templates/get_tutorial.html @@ -0,0 +1,12 @@ +{% extends 'website/templates/base.html' %} +{% block content %} +<h4>{{question.title}}</h4> +<p> + {{ question.body }} +</p> + +<b>Replies</b> +{% for reply in replies %} + {{ reply.body }} +{% endfor %} +{% endblock %} diff --git a/static/website/templates/index.html b/static/website/templates/index.html index c8b11b3..471fb48 100644 --- a/static/website/templates/index.html +++ b/static/website/templates/index.html @@ -5,11 +5,11 @@ <a href="{% url 'website:fetch_tutorials' category %}">{{ category }}</a> <br> {% load count_tags %} - <span class="posts"> - {% category_post_count category %} posts, + <span class="questions"> + {% category_question_count category %} questions, </span> <span class="replies"> - {% category_post_count category %} replies + {% category_question_count category %} replies </span> <span class="helper"> A diff --git a/static/website/templates/new-post.html b/static/website/templates/new-post.html new file mode 100644 index 0000000..8487b70 --- /dev/null +++ b/static/website/templates/new-post.html @@ -0,0 +1,45 @@ +{% extends 'website/templates/base.html' %} +{% load widget_tweaks %} +{% block content %} + <h4> + <span class="glyphicon glyphicon-pencil"> + </span> Create a new question . . . + </h4> + <hr> + <form role="form" action="" method="POST"> + {% with WIDGET_ERROR_CLASS='field_error' %} + + <p>Please enter the tutorial details.</p> + <div class="row"> + <div class="col-lg-3 col-md-4 col-sm-4"> + {% render_field form.category class+="form-control"%} + </div> + <div class="col-lg-3 col-md-4 col-sm-4"> + {% render_field form.tutorial class+="form-control" disabled="disabled" %} + </div> + <div class="col-lg-2 col-md-2 col-sm-2"> + {% render_field form.minute_range class+="form-control" disabled="disabled" %} + </div> + <div class="col-lg-2 col-md-2 col-sm-2"> + {% render_field form.second_range class+="form-control" disabled="disabled" %} + </div> + </div> + <hr> + + <p>Please enter your question details.</p> + <div class="row"> + <div class="col-lg-10"> + <div class="form-group"> + <label for="id_title">Title:</label> + {% render_field form.title class+="form-control" %} + </div> + <div class="form-group"> + <label for="id_body">Question:</label> + {% render_field form.body class+="form-control" %} + </div> + </div> + </div> + <input class="btn btn-success" type="submit" value="Submit Question"> + {% endwith %} + </form> +{% endblock %} diff --git a/static/website/templates/new-question.html b/static/website/templates/new-question.html new file mode 100644 index 0000000..5005e13 --- /dev/null +++ b/static/website/templates/new-question.html @@ -0,0 +1,45 @@ +{% extends 'website/templates/base.html' %} +{% load widget_tweaks %} +{% block content %} + <h4> + <span class="glyphicon glyphicon-pencil"> + </span> Create a new question . . . + </h4> + <hr> + <form role="form" action="" method="POST">{% csrf_token %} + {% with WIDGET_ERROR_CLASS='field_error' %} + + <p>Please enter the tutorial details.</p> + <div class="row"> + <div class="col-lg-3 col-md-4 col-sm-4"> + {% render_field form.category class+="form-control"%} + </div> + <div class="col-lg-3 col-md-4 col-sm-4"> + {% render_field form.tutorial class+="form-control" disabled="disabled" %} + </div> + <div class="col-lg-2 col-md-2 col-sm-2"> + {% render_field form.minute_range class+="form-control" disabled="disabled" %} + </div> + <div class="col-lg-2 col-md-2 col-sm-2"> + {% render_field form.second_range class+="form-control" disabled="disabled" %} + </div> + </div> + <hr> + + <p>Please enter your question details.</p> + <div class="row"> + <div class="col-lg-10"> + <div class="form-group"> + <label for="id_title">Title:</label> + {% render_field form.title class+="form-control" %} + </div> + <div class="form-group"> + <label for="id_body">Question:</label> + {% render_field form.body class+="form-control" %} + </div> + </div> + </div> + <input class="btn btn-success" type="submit" value="Submit Question"> + {% endwith %} + </form> +{% endblock %} diff --git a/static/website/templates/recent_questions.html b/static/website/templates/recent_questions.html new file mode 100644 index 0000000..1a4cc44 --- /dev/null +++ b/static/website/templates/recent_questions.html @@ -0,0 +1,5 @@ +<ul> +{% for question in recent_questions %} + <li>{{question.title}}</li> +{% endfor %} +</ul> diff --git a/website/forms.py b/website/forms.py new file mode 100644 index 0000000..00b0cfe --- /dev/null +++ b/website/forms.py @@ -0,0 +1,71 @@ +from django import forms + +from website.models import Question + +categories = ( + ("None", "Select a Category"), + ('Advanced-C++', 'Advanced-C++'), + ('BASH', 'BASH'), + ('Blender', 'Blender'), + ('C-and-C++', 'C-and-C++'), + ('CellDesigner', 'CellDesigner'), + ('Digital-Divide', 'Digital-Divide'), + ('Drupal', 'Drupal'), + ('Firefox', 'Firefox'), + ('GChemPaint', 'GChemPaint'), + ('Geogebra', 'Geogebra'), + ('GeoGebra-for-Engineering-drawing', 'GeoGebra-for-Engineering-drawing'), + ('GIMP', 'GIMP'), + ('GNS3', 'GNS3'), + ('GSchem', 'GSchem'), + ('Java', 'Java'), + ('Java-Business-Application', 'Java-Business-Application'), + ('KiCad', 'KiCad'), + ('KTouch', 'KTouch'), + ('KTurtle', 'KTurtle'), + ('LaTeX', 'LaTeX'), + ('LibreOffice-Suite-Base', 'LibreOffice-Suite-Base'), + ('LibreOffice-Suite-Calc', 'LibreOffice-Suite-Calc'), + ('LibreOffice-Suite-Draw', 'LibreOffice-Suite-Draw'), + ('LibreOffice-Suite-Impress', 'LibreOffice-Suite-Impress'), + ('LibreOffice-Suite-Math', 'LibreOffice-Suite-Math'), + ('LibreOffice-Suite-Writer', 'LibreOffice-Suite-Writer'), + ('Linux', 'Linux'), + ('Netbeans', 'Netbeans'), + ('Ngspice', 'Ngspice'), + ('OpenFOAM', 'OpenFOAM'), + ('Orca', 'Orca'), + ('PERL', 'PERL'), + ('PHP-and-MySQL', 'PHP-and-MySQL'), + ('Python', 'Python'), + ('Python-Old-Version', 'Python-Old-Version'), + ('QCad', 'QCad'), + ('R', 'R'), + ('Ruby', 'Ruby'), + ('Scilab', 'Scilab'), + ('Selenium', 'Selenium'), + ('Single-Board-Heater-System', 'Single-Board-Heater-System'), + ('Spoken-Tutorial-Technology', 'Spoken-Tutorial-Technology'), + ('Step', 'Step'), + ('Thunderbird', 'Thunderbird'), + ('Tux-Typing', 'Tux-Typing'), + ('What-is-Spoken-Tutorial', 'What-is-Spoken-Tutorial'), + ('Xfig', 'Xfig') +) +tutorials = ( + ("None", "Select a Tutorial"), +) +minutes = ( + ("None", "min"), +) +seconds= ( + ("None", "sec"), +) + +class NewQuestionForm(forms.Form): + category = forms.CharField(widget=forms.Select(choices=categories)) + tutorial = forms.CharField(widget=forms.Select(choices=tutorials)) + minute_range = forms.CharField(widget=forms.Select(choices=minutes)) + second_range = forms.CharField(widget=forms.Select(choices=seconds)) + title = forms.CharField(max_length=200) + body = forms.CharField(widget=forms.Textarea()) diff --git a/website/helpers.py b/website/helpers.py index dd37152..0d67da0 100644 --- a/website/helpers.py +++ b/website/helpers.py @@ -20,6 +20,9 @@ def get_video_info(path): total += 60 * minutes total += seconds + info_m['hours'] = hours + info_m['minutes'] = minutes + info_m['seconds'] = seconds info_m['duration'] = total info_m['width'] = int(info_m['width']) info_m['height'] = int(info_m['height']) diff --git a/website/models.py b/website/models.py index 9570965..ce8d4dc 100644 --- a/website/models.py +++ b/website/models.py @@ -1,10 +1,14 @@ from django.db import models from django.contrib.auth.models import User -class Post(models.Model): +class Question(models.Model): user = models.ForeignKey(User) category = models.CharField(max_length=200) tutorial = models.CharField(max_length=200) + minute_start = models.IntegerField() + minute_end = models.IntegerField() + second_start = models.IntegerField() + second_end = models.IntegerField() title = models.CharField(max_length=200) body = models.TextField() date_created = models.DateTimeField(auto_now_add=True) @@ -12,7 +16,7 @@ class Post(models.Model): class Reply(models.Model): user = models.ForeignKey(User) - post = models.ForeignKey(Post) + question = models.ForeignKey(Question) title = models.CharField(max_length=200) body = models.TextField() date_created = models.DateTimeField(auto_now_add=True) diff --git a/website/templatetags/count_tags.py b/website/templatetags/count_tags.py index e4233f1..33aff7f 100644 --- a/website/templatetags/count_tags.py +++ b/website/templatetags/count_tags.py @@ -1,11 +1,61 @@ from django import template -from website.models import Post, Reply +from website.models import Question, Reply register = template.Library() -def category_post_count(category): - category_post_count = Post.objects.filter(category=category).count() - return category_post_count -register.simple_tag(category_post_count) +# Counts the number of questions in <category> +def category_question_count(category): + category_question_count =Question.objects.filter(category=category).count() + return category_question_count +register.simple_tag(category_question_count) +# Implementing range(x) function in templates +def get_range(value, arg=''): + args = arg.split(',') + n = len(args) + + if n == 0 or arg =='': + # if no arguments set value as limit + start = 0 + limit = value + step = 1 + elif n == 1: + start = int(args[0]) + limit = value + step = 1 + elif n == 2: + start = int(args[0]) + limit = value + step = int(args[1]) + else: + raise TypeError('get_range() takes maximum 2 arguments, {} given'.format(n)) + + return range(start, limit, step) +register.filter('get_range', get_range) + +# Implementing increment and decrement functions +def inc(value, arg=1): + return value + int(arg) +register.filter('inc', inc) + +def dec(value, arg=1): + return value-int(arg) +register.filter('dec', dec) + +# Implementing calculator for templates +def add(value, arg=0): + return value + int(arg) +register.filter('add', add) + +def sub(value, arg=0): + return value - int(arg) +register.filter('sub', sub) + +def mul(value, arg=1): + return value * int(arg) +register.filter('mul', mul) + +def div(value, arg=1): + return value / int(arg) +register.filter('div', div) diff --git a/website/templatetags/sidebar_tags.py b/website/templatetags/sidebar_tags.py index a7e5cc7..8b7efb9 100644 --- a/website/templatetags/sidebar_tags.py +++ b/website/templatetags/sidebar_tags.py @@ -1,12 +1,11 @@ from django import template -from website.models import Post, Reply +from website.models import Question, Reply register = template.Library() -def recent_posts(): - recent_posts = Post.objects.all().order_by('-id')[:5] - return {'recent_posts': recent_posts} - -register.inclusion_tag('website/templates/recent_posts.html')(recent_posts) +def recent_questions(): + recent_questions = Question.objects.all().order_by('-id')[:5] + return {'recent_questions': recent_questions} +register.inclusion_tag('website/templates/recent_questions.html')(recent_questions) diff --git a/website/urls.py b/website/urls.py index 29c25ea..9d1b048 100644 --- a/website/urls.py +++ b/website/urls.py @@ -3,7 +3,11 @@ from django.conf.urls import patterns, include, url urlpatterns = patterns('', url(r'^$', 'website.views.home', name='home'), url(r'^category/(?P<category>.+)/$', 'website.views.fetch_tutorials', name='fetch_tutorials'), - url(r'^tutorial/(?P<category>.+)/(?P<tutorial>.+)/$', 'website.views.fetch_posts', name='fetch_posts'), - url(r'^post/(?P<post_id>\d+)$', 'website.views.get_post', name='get_post'), - url(r'^new-post/$', 'website.views.new_post', name='new_post'), + url(r'^tutorial/(?P<category>.+)/(?P<tutorial>.+)/$', 'website.views.fetch_questions', name='fetch_questions'), + url(r'^question/(?P<question_id>\d+)$', 'website.views.get_question', name='get_question'), + url(r'^new-question/$', 'website.views.new_question', name='new_question'), + + # Ajax helpers + url(r'^ajax-tutorials/$', 'website.views.ajax_tutorials', name='ajax_tutorials'), + url(r'^ajax-duration/$', 'website.views.ajax_duration', name='ajax_duration'), ) diff --git a/website/views.py b/website/views.py index 0a8f43b..c5b71af 100644 --- a/website/views.py +++ b/website/views.py @@ -1,9 +1,11 @@ -import math - from django.http import HttpResponse, HttpResponseRedirect from django.shortcuts import render_to_response, get_object_or_404 +from django.core.context_processors import csrf +from django.views.decorators.csrf import csrf_exempt +from django.contrib.auth.decorators import login_required -from website.models import Post, Reply, TutorialDetails, TutorialResources +from website.models import Question, Reply, TutorialDetails, TutorialResources +from website.forms import NewQuestionForm from website.helpers import get_video_info categories = [ @@ -37,48 +39,68 @@ def fetch_tutorials(request, category=None): } return render_to_response('website/templates/fetch_tutorials.html', context) -def fetch_posts(request, category=None, tutorial=None): - posts = Post.objects.filter(category=category).filter(tutorial=tutorial) +def fetch_questions(request, category=None, tutorial=None): + questions = Question.objects.filter(category=category).filter(tutorial=tutorial) context = { 'category': category, 'tutorial': tutorial, - 'posts': posts + 'questions': questions } - return render_to_response('website/templates/fetch_posts.html', context) + return render_to_response('website/templates/fetch_questions.html', context) -def get_post(request, post_id=None): - post = get_object_or_404(Post, id=post_id) - replies = post.reply_set.all() +def get_question(request, question_id=None): + question = get_object_or_404(Question, id=question_id) + replies = question.reply_set.all() context = { - 'post': post, + 'question': question, 'replies': replies } - return render_to_response('website/templates/get_post.html', context) - -def new_post(request): - video_info = get_video_info('/home/cheese/test-video.ogv') - duration = math.ceil(video_info['duration']/60) #assuming the video is less than an hour - return HttpResponse(duration) - - - - - - - - - - - - - - - - - - - - + return render_to_response('website/templates/get_question.html', context) +@login_required +def new_question(request): + if request.method == 'POST': + form = NewQuestionForm(request.POST) + if form.is_valid(): + return HttpResponse("valid") + else: + form = NewQuestionForm() + context = { + 'form': form + } + context.update(csrf(request)) + return render_to_response('website/templates/new-question.html', context) + +@csrf_exempt +def ajax_tutorials(request): + if request.method == 'POST': + category = request.POST.get('category') + tutorials = TutorialDetails.objects.using('spoken').filter(foss_category=category) + context = { + 'tutorials': tutorials + } + return render_to_response('website/templates/ajax-tutorials.html', context) + +@csrf_exempt +def ajax_duration(request): + if request.method == 'POST': + category = request.POST['category'] + tutorial =request.POST['tutorial'] + video_info = get_video_info('/home/cheese/test-video.ogv') + + # convert minutes to 1 if less than 0 + # convert seconds to nearest upper 10th number eg(23->30) + minutes = video_info['minutes'] + seconds = video_info['seconds'] + if minutes < 0: + minutes = 1 + seconds = int(seconds - (seconds % 10 - 10)) + + print minutes, seconds + context = { + 'minutes': minutes, + 'seconds':seconds, + } + return render_to_response('website/templates/ajax-duration.html', context) |