summaryrefslogtreecommitdiff
path: root/tbc
diff options
context:
space:
mode:
Diffstat (limited to 'tbc')
-rw-r--r--tbc/models.py7
-rwxr-xr-xtbc/templates/base.html9
-rw-r--r--tbc/templates/tbc/book-review-details.html14
-rw-r--r--tbc/templates/tbc/book-review.html6
-rw-r--r--tbc/templates/tbc/review-proposal.html16
-rw-r--r--tbc/templates/tbc/submit-sample.html2
-rwxr-xr-xtbc/views.py116
7 files changed, 144 insertions, 26 deletions
diff --git a/tbc/models.py b/tbc/models.py
index ec4c35d..15daca9 100644
--- a/tbc/models.py
+++ b/tbc/models.py
@@ -1,6 +1,7 @@
from django.db import models
from django.contrib.auth.models import User
from PythonTBC import settings
+from django.contrib.admin.models import LogEntry
CATEGORY = (("fluid mechanics", "Fluid Mechanics"),
@@ -151,6 +152,12 @@ class SampleNotebook(models.Model):
return '%s'%(notebook)
+class ActivityLog(LogEntry):
+ proposal_id = models.IntegerField(null=True)
+ def __unicode__(self):
+ return 'Activity log for %d' %(proposal_id)
+
+
class AicteBook(models.Model):
title = models.TextField()
author = models.CharField(max_length=300L)
diff --git a/tbc/templates/base.html b/tbc/templates/base.html
index 803ad4d..80a8694 100755
--- a/tbc/templates/base.html
+++ b/tbc/templates/base.html
@@ -207,6 +207,15 @@
</center>
<div class="clearfix"></div>
{% endif %}
+ {% if cannot_submit_sample %}
+ <center>
+ <div class="alert" style="width:400px;height:25px;">
+ <a class="close" data-dismiss="alert" href="#">&times;</a>
+ <p>You have not been permitted to send sample notebook.</p>
+ </div>
+ </center>
+ <div class="clearfix"></div>
+ {% endif %}
<div class="row-fluid">
<center><h3>Recent Submissions</h3></center>
{% for item in items %}
diff --git a/tbc/templates/tbc/book-review-details.html b/tbc/templates/tbc/book-review-details.html
index e55c23c..f304a66 100644
--- a/tbc/templates/tbc/book-review-details.html
+++ b/tbc/templates/tbc/book-review-details.html
@@ -33,4 +33,18 @@
<tr><td>Contributor: &nbsp;&nbsp;<td>{{ book.contributor.user.first_name }} {{ book.contributor.user.last_name }}
<tr><td>Email: &nbsp;&nbsp;<td>{{ book.contributor.user.email }}<br>
</table>
+<table class='table'>
+ <tr>
+ <th>User</th>
+ <th>Time</th>
+ <th>Activity</th>
+ </tr>
+{% for log in logs %}
+<tr>
+ <td> {{ log.user }} </td>
+ <td> {{ log.action_time }} </td>
+ <td> {{ log.change_message }} </td>
+</tr>
+{% endfor %}
+<table>
{% endblock %}
diff --git a/tbc/templates/tbc/book-review.html b/tbc/templates/tbc/book-review.html
index 774998c..98d569a 100644
--- a/tbc/templates/tbc/book-review.html
+++ b/tbc/templates/tbc/book-review.html
@@ -13,4 +13,10 @@
<li><a href="{% url 'tbc:BookReview' book.id %}">{{ book.title }} {{ book.edition }} Edition</a>
{% endfor %}
</ol>
+<center><h3>Reviewed Books</h3></center>
+<ol>
+{% for book in approved_books %}
+<li><a href="{% url 'tbc:BookReview' book.id %}">{{ book.title }} {{ book.edition }} Edition</a></li>
+{% endfor %}
+<ol>
{% endblock %}
diff --git a/tbc/templates/tbc/review-proposal.html b/tbc/templates/tbc/review-proposal.html
index a71ebfc..c0ea983 100644
--- a/tbc/templates/tbc/review-proposal.html
+++ b/tbc/templates/tbc/review-proposal.html
@@ -8,16 +8,16 @@
{% endif %}
<ol>
{% for proposal in proposals %}
- <li><h4>Propsal from {{ proposal.user.user.first_name }} {{ proposal.user.user.last_name }}</h4></li>
- <div class="accordion" id="accordion{{ forloop.counter }}">
+ <li><h4>Proposal from {{ proposal.user.user.first_name }} {{ proposal.user.user.last_name }}</h4></li>
+ <div class="accordion" id="accordion1{{ forloop.parentloop.counter }}{{ forloop.counter }}">
{% for textbook in proposal.textbooks.all %}
<div class="accordion-group">
<div class="accordion-heading">
- <a class="accordion-toggle" data-toggle="collapse" data-parent="#accordion{{ forloop.counter }}" href="#collapse{{forloop.counter}}">
+ <a class="accordion-toggle" data-toggle="collapse" data-parent="#accordion1{{ forloop.parentloop.counter }}{{ forloop.counter }}" href="#collapse1{{ forloop.parentloop.counter }}{{forloop.counter}}">
Book Preference {{ forloop.counter }} - {{ textbook.title }}
</a>
</div>
- <div id="collapse{{forloop.counter}}" class="accordion-body collapse">
+ <div id="collapse1{{ forloop.parentloop.counter }}{{forloop.counter}}" class="accordion-body collapse">
<div class="accordion-inner">
Author: {{ textbook.author}}<br>
Edition: {{ textbook.edition }}<br>
@@ -40,16 +40,16 @@
<hr>
<ol>
{% for proposal in old_proposals %}
- <h4><li>Propsal from {{ proposal.proposal.user.user.first_name }} {{ proposal.proposal.user.user.last_name }}</h4></li>
- <div class="accordion" id="accordion{{ forloop.counter }}">
+ <h4><li>Proposal from {{ proposal.proposal.user.user.first_name }} {{ proposal.proposal.user.user.last_name }}</h4></li>
+ <div class="accordion" id="accordion2{{ forloop.counter }}">
{% for textbook in proposal.proposal.textbooks.all %}
<div class="accordion-group">
<div class="accordion-heading">
- <a class="accordion-toggle" data-toggle="collapse" data-parent="#accordion{{ forloop.counter }}" href="#collapse{{forloop.counter}}">
+ <a class="accordion-toggle" data-toggle="collapse" data-parent="#accordion2{{ forloop.parentloop.counter }}{{ forloop.counter }}" href="#collapse2{{ forloop.parentloop.counter }}{{forloop.counter}}">
Book Preference {{ forloop.counter }} - {{ textbook.title }}
</a>
</div>
- <div id="collapse{{forloop.counter}}" class="accordion-body collapse">
+ <div id="collapse2{{ forloop.parentloop.counter }}{{forloop.counter}}" class="accordion-body collapse">
<div class="accordion-inner">
Author: {{ textbook.author}}<br>
Edition: {{ textbook.edition }}<br>
diff --git a/tbc/templates/tbc/submit-sample.html b/tbc/templates/tbc/submit-sample.html
index f259ffc..96f1209 100644
--- a/tbc/templates/tbc/submit-sample.html
+++ b/tbc/templates/tbc/submit-sample.html
@@ -29,7 +29,7 @@ function validate_content()
{% if has_old %}
<form action="/submit-sample/{{ proposal.id }}/{{ old_notebook.id }}" name="with-old" method=POST enctype="multipart/form-data" onSubmit="return validate_content();">
{% csrf_token %}
- <input type=text id=ch_name_old name=ch_name_old placeholder="{{ old_notebook.title }}">
+ <input type=text id=ch_name_old name=ch_name_old value="{{ old_notebook.name }}">
<input type=file id=old_notebook name=old_notebook>
<br>
<hr>
diff --git a/tbc/views.py b/tbc/views.py
index 8582538..b93a065 100755
--- a/tbc/views.py
+++ b/tbc/views.py
@@ -1,8 +1,11 @@
+from django.utils.encoding import force_text
+from django.contrib.contenttypes.models import ContentType
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render_to_response, redirect
from django.views.decorators.csrf import csrf_exempt
from django.core.context_processors import csrf
from django.contrib.auth import authenticate, login, logout
+from django.contrib.admin.models import CHANGE
from models import *
from tbc.forms import *
import os
@@ -16,6 +19,19 @@ import json
from email.mime.text import MIMEText
+def add_log(user, object, flag, message, proposal_id=None):
+ '''Creates log entry of the user activities.'''
+ ActivityLog(
+ user_id=user.id,
+ content_type_id=ContentType.objects.get_for_model(object).id,
+ object_id=object.id,
+ object_repr=force_text(object),
+ action_flag=flag,
+ change_message=message,
+ proposal_id = proposal_id,
+ ).save()
+
+
def email_send(to,subject,msg):
try:
smtpObj = smtplib.SMTP('localhost')
@@ -90,6 +106,8 @@ def Home(request):
context['no_book_alloted'] = True
if 'sample_notebook' in request.GET:
context['sample_notebook'] = True
+ if 'cannot_submit_sample' in request.GET:
+ context['cannot_submit_sample'] =True
books = Book.objects.filter(approved=True).order_by("-id")[0:6]
for book in books:
@@ -120,6 +138,7 @@ def UserLogin(request):
curr_user = authenticate(username=username, password=password)
if curr_user is not None:
login(request, curr_user)
+ add_log(curr_user, curr_user, CHANGE, 'Logged in')
else:
form = UserLoginForm()
context['form'] = form
@@ -147,7 +166,8 @@ def UserRegister(request):
if request.method == 'POST':
form = UserRegisterForm(request.POST)
if form.is_valid():
- form.save()
+ user = form.save()
+ add_log(user, user, CHANGE, 'Registered')
return HttpResponseRedirect('/login/?signup=done')
else:
context = {}
@@ -166,11 +186,16 @@ def UserProfile(request):
user = request.user
if user.is_authenticated():
if request.method == 'POST':
- form = UserProfileForm(request.POST)
+ user_profile = Profile.objects.filter(user=user)
+ if user_profile.exists():
+ form = UserProfileForm(request.POST, instance=user_profile[0])
+ else:
+ form = UserProfileForm(request.POST)
if form.is_valid():
data = form.save(commit=False)
data.user = request.user
data.save()
+ add_log(user, user, CHANGE,'Profile entry')
return HttpResponseRedirect('/')
else:
context = {}
@@ -194,6 +219,7 @@ def UserLogout(request):
user = request.user
if user.is_authenticated() and user.is_active:
logout(request)
+ add_log(user, user, CHANGE, 'Logged out')
return redirect('/?logout=done')
@@ -250,6 +276,7 @@ def UpdatePassword(request):
if new_password == confirm:
user.set_password(new_password)
user.save()
+ add_log(user, user, CHANGE, 'Password updated')
form = UserLoginForm()
context['password_updated'] = True
context['form'] = form
@@ -285,6 +312,8 @@ def SubmitBook(request):
context['user'] = curr_user
curr_book = Book.objects.order_by("-id")[0]
curr_book_id = curr_book.id
+ proposal_id = Proposal.objects.get(accepted=curr_book)
+ add_log(curr_user, curr_book, CHANGE, 'Book submitted', proposal_id)
return HttpResponseRedirect('/upload-content/'+str(curr_book_id))
else:
context.update(csrf(request))
@@ -305,14 +334,25 @@ def SubmitProposal(request):
context = {}
context.update(csrf(request))
context['user'] = curr_user
- user_proposals = Proposal.objects.filter(user=user_profile)
- can_submit_new = True
+ user_proposals = list(Proposal.objects.filter(user=user_profile))
+ proposal_id = None
+ can_submit_new = False
matching_books = []
- for proposal in user_proposals:
- if proposal.status is not "book completed":
- can_submit_new = False
+ if user_proposals:
+ if user_proposals[-1].status == 'rejected':
+ can_submit_new = True
+ proposal_id = user_proposals[-1].id
+ else:
+ can_submit_new = True
if can_submit_new:
if request.method == 'POST':
+ try:
+ proposal = Proposal.objects.get(id=proposal_id)
+ except:
+ proposal = Proposal()
+ proposal.user = user_profile
+ proposal.status = 'Pending'
+ proposal.save()
book_titles = request.POST.getlist('title')
book_authors = request.POST.getlist('author')
book_categories = request.POST.getlist('category')
@@ -321,8 +361,12 @@ def SubmitProposal(request):
book_editions = request.POST.getlist('edition')
book_years = request.POST.getlist('year_of_pub')
book_chapters = request.POST.getlist('no_chapters')
+ textbooks = proposal.textbooks.all()
for item in range(3):
- tempbook = TempBook()
+ if textbooks:
+ tempbook = textbooks[item]
+ else:
+ tempbook = TempBook()
tempbook.title = book_titles[item]
tempbook.author = book_authors[item]
tempbook.category = book_categories[item]
@@ -332,16 +376,26 @@ def SubmitProposal(request):
tempbook.year_of_pub = book_years[item]
tempbook.no_chapters = book_chapters[item]
tempbook.save()
- proposal = Proposal()
- proposal.user = user_profile
- proposal.save()
- for book in list(TempBook.objects.all())[-3:]:
- proposal.textbooks.add(book)
+ if not textbooks:
+ proposal.textbooks.add(tempbook)
+ add_log(curr_user, proposal, CHANGE, 'Proposed Books', proposal.id)
return HttpResponseRedirect('/?proposal=submitted')
else:
book_forms = []
for i in range(3):
form = BookForm()
+ if proposal_id:
+ proposal = Proposal.objects.get(id=proposal_id)
+ textbooks = proposal.textbooks.all()
+ form.initial['title'] = textbooks[i].title
+ form.initial['author'] = textbooks[i].author
+ form.initial['category'] = textbooks[i].category
+ form.initial['publisher_place'] = textbooks[i].publisher_place
+ form.initial['isbn'] = textbooks[i].isbn
+ form.initial['edition'] = textbooks[i].edition
+ form.initial['year_of_pub'] = textbooks[i].year_of_pub
+ form.initial['no_chapters'] = textbooks[i].no_chapters
+
book_forms.append(form)
context['book_forms'] = book_forms
return render_to_response('tbc/submit-proposal.html', context)
@@ -437,6 +491,7 @@ def ReviewProposals(request, proposal_id=None, textbook_id=None):
proposal.status = "samples"
proposal.accepted = new_book
proposal.save()
+ add_log(request.user, proposal, CHANGE, 'Proposal accepted', proposal.id)
return HttpResponse("Approved")
else:
new_proposals = Proposal.objects.filter(status="pending")
@@ -466,6 +521,7 @@ def DisapproveProposal(request, proposal_id=None):
context.update(csrf(request))
proposal = Proposal.objects.get(id=proposal_id)
if request.method == 'POST':
+ add_log(request.user, proposal, CHANGE, 'Sample disapproved', proposal_id)
changes_required = request.POST['changes_required']
subject = "Python-TBC: Corrections Required in the sample notebook"
message = "Hi, "+proposal.user.user.first_name+",\n"+\
@@ -480,11 +536,12 @@ def DisapproveProposal(request, proposal_id=None):
return render_to_response('tbc/disapprove-sample.html', context)
-def AllotBook(requrest, proposal_id=None):
+def AllotBook(request, proposal_id=None):
context = {}
proposal = Proposal.objects.get(id=proposal_id)
proposal.status = "book alloted"
proposal.save()
+ add_log(request.user, proposal, CHANGE, 'Book alloted', proposal_id)
return HttpResponseRedirect("/book-review/?book_alloted=done")
@@ -495,6 +552,7 @@ def RejectProposal(request, proposal_id=None):
if request.method == 'POST':
proposal.status = 'rejected'
proposal.save()
+ add_log(request.user, proposal, CHANGE, 'Proposal rejected', proposal.id)
remarks = request.POST['remarks']
subject = "Python-TBC: Rejection of Proposal"
message = "Dear "+proposal.user.user.first_name+"\nYour proposal has been\
@@ -512,8 +570,14 @@ def SubmitSample(request, proposal_id=None, old_notebook_id=None):
context.update(csrf(request))
if request.method == "POST":
curr_proposal = Proposal.objects.get(id=proposal_id)
+ add_log(request.user, curr_proposal, CHANGE, 'Sample Submitted', curr_proposal.id)
if old_notebook_id:
- pass
+ old_notebook = SampleNotebook.objects.get(id=old_notebook_id)
+ old_notebook.proposal = curr_proposal
+ old_notebook.name = request.POST.get('ch_name_old')
+ old_notebook.sample_notebook = request.FILES['old_notebook']
+ old_notebook.save()
+ return HttpResponseRedirect('/?sample_notebook=done')
else:
sample_notebook = SampleNotebook()
sample_notebook.proposal = curr_proposal
@@ -523,7 +587,10 @@ def SubmitSample(request, proposal_id=None, old_notebook_id=None):
return HttpResponseRedirect('/?sample_notebook=done')
else:
profile = Profile.objects.get(user=request.user)
- proposal = Proposal.objects.get(user=profile, status='samples')
+ try:
+ proposal = Proposal.objects.get(user=profile, status='samples')
+ except Proposal.DoesNotExist:
+ return HttpResponseRedirect('/?cannot_submit_sample=True')
try:
old_notebook = SampleNotebook.objects.get(proposal=proposal)
context['has_old'] = True
@@ -559,6 +626,8 @@ def UpdateBook(request):
data.save()
context.update(csrf(request))
context['form'] = book_form
+ proposal = Proposal.objects.get(accepted=book_to_update)
+ add_log(current_user, book_to_update, CHANGE, 'Book updated', proposal.id)
return HttpResponseRedirect('/update-content/'+str(book_to_update.id))
else:
book_form = BookForm()
@@ -598,6 +667,8 @@ def SubmitCode(request):
screenshot.book = curr_book
screenshot.save()
book = Book.objects.order_by("-id")[0]
+ proposal = Proposal.objects.get(accepted=book)
+ add_log(user, curr_book, CHANGE, 'Chapters and Screenshots added', proposal.id)
subject = "Python-TBC: Book Submission"
message = "Hi "+curr_book.reviewer.name+",\n"+\
"A book has been submitted on the Python TBC interface.\n"+\
@@ -640,6 +711,8 @@ def UpdateContent(request, book_id=None):
screenshot.image = request.FILES['image'+str(i)]
screenshot.book = current_book
screenshot.save()
+ proposal = Proposal.objects.get(accepted=current_book)
+ add_log(user, current_book, CHANGE, 'book updated', proposal.id)
subject = "Python-TBC: Book Updated"
message = "Hi "+current_book.reviewer.name+",\n"+\
"Submission for a book has been updated on the Python TBC interface.\n"+\
@@ -651,7 +724,7 @@ def UpdateContent(request, book_id=None):
"ISBN: "+current_book.isbn+"\n"+\
"Follow the link to review the book: \n"+\
"http://dev.fossee.in/book-review/"+str(current_book.id)
- email_send(current_book.reviewer.email, subject, message)
+ email_send(current_book.reviewer.email, subject, message, current_book.id)
return HttpResponseRedirect('/?update_book=done')
else:
context.update(csrf(request))
@@ -715,6 +788,9 @@ def BookReview(request, book_id=None):
book = Book.objects.get(id=book_id)
chapters = Chapters.objects.filter(book=book)
images = ScreenShots.objects.filter(book=book)
+ proposal = Proposal.objects.get(accepted=book)
+ logs = ActivityLog.objects.filter(proposal_id=proposal.id)
+ context['logs'] = logs
context['chapters'] = chapters
context['images'] = images
context['book'] = book
@@ -727,6 +803,8 @@ def BookReview(request, book_id=None):
if 'mail_notify' in request.GET:
context['mail_notify'] = True
books = Book.objects.filter(approved=False)
+ approved_books = Book.objects.filter(approved=True)
+ context['approved_books'] = approved_books
context['books'] = books
context['reviewer'] = request.user
context.update(csrf(request))
@@ -743,6 +821,8 @@ def ApproveBook(request, book_id=None):
book = Book.objects.get(id=book_id)
book.approved = True
book.save()
+ proposal = Proposal.objects.get(accepted=book)
+ add_log(user, book, CHANGE, 'Book approved', proposal.id)
file_path = os.path.abspath(os.path.dirname(__file__))
zip_path = "/".join(file_path.split("/")[1:-2])
zip_path = "/"+zip_path+"/Python-Textbook-Companions/"
@@ -791,8 +871,10 @@ def NotifyChanges(request, book_id=None):
context = {}
if is_reviewer(request.user):
book = Book.objects.get(id=book_id)
+ proposal = Proposal.objects.get(accepted=book)
if request.method == 'POST':
changes_required = request.POST['changes_required']
+ add_log(request.user, book, CHANGE, 'Changes notification', proposal.id)
subject = "Python-TBC: Corrections Required"
message = "Hi, "+book.contributor.user.first_name+",\n"+\
"Book titled, "+book.title+" requires following changes: \n"+\