Clean-up / modernize templates and views

This commit is contained in:
Scot Hacker 2016-04-09 02:23:11 -07:00
parent 8ee28118fe
commit 37aef01c0f
9 changed files with 354 additions and 429 deletions

View file

@ -4,13 +4,11 @@
{% block content %} {% block content %}
<h2>{{ task }}</h2> <h2>{{ task }}</h2>
<form action="" method="POST"> <form action="" method="POST">
{% csrf_token %} {% csrf_token %}
{% if task.note %} {% if task.note %}
<div class="task_note"><strong>Note:</strong> {{ task.note|safe|urlize|linebreaks }}</div> <div class="task_note"><strong>Note:</strong> {{ task.note|safe|urlize|linebreaks }}</div>
{% endif %} {% endif %}
@ -31,43 +29,34 @@
{% endif %} {% endif %}
<table> <table>
{{ form.management_form }} {{ form.management_form }}
{{ form.id }} {{ form.id }}
<tr> <tr>
<td>Summary:</td> <td>Summary:</td>
<td>{{ form.title }} <br /> <td>{{ form.title }} <br />
Include the workstation number in your summary, e.g. <br /> Include the workstation number in your summary, e.g. <br />
"Radio Lab # 4: Purple smoke pouring out the back." "Radio Lab # 4: Purple smoke pouring out the back."
</td> </td>
</tr> </tr>
<tr> <tr>
<td valign="top">Note:</td> <td valign="top">Note:</td>
<td valign="top">{{ form.note }}<br /> <td valign="top">{{ form.note }}<br />
Please describe the problem. </td> Please describe the problem.
</td>
</tr> </tr>
<tr> <tr>
<td>Priority:</td> <td>Priority:</td>
<td>{{ form.priority }} <br /> <td>{{ form.priority }} <br />
Enter a number between 1 and 5, <br /> Enter a number between 1 and 5, <br />
where 5 is highest ("Computer is on fire = True"). where 5 is highest ("Computer is on fire = True").
</td> </td>
</tr> </tr>
</table> </table>
<p><input type="submit" class="todo-button" name="add_task" value="Submit"></p> <p><input type="submit" class="todo-button" name="add_task" value="Submit"></p>
</div> </div>
</form> </form>
{% endblock %} {% endblock %}

View file

@ -1,4 +1,5 @@
{% extends "todo/base.html" %} {% extends "todo/base.html" %}
{% block page_heading %}{% endblock %} {% block page_heading %}{% endblock %}
{% block title %}Add Todo List{% endblock %} {% block title %}Add Todo List{% endblock %}

View file

@ -4,15 +4,12 @@
{% block extrahead %} {% block extrahead %}
<!-- CSS and JavaScript for django-todo --> <!-- CSS and JavaScript for django-todo -->
<link rel="stylesheet" type="text/css" href="{% static 'todo/css/styles.css' %}" /> <link rel="stylesheet" type="text/css" href="{% static 'todo/css/styles.css' %}" />
<script src="{% static 'todo/js/jquery.tablednd_0_5.js' %}" type="text/javascript"></script> <script src="{% static 'todo/js/jquery.tablednd_0_5.js' %}" type="text/javascript"></script>
<script type="text/javascript" charset="utf-8"> <script type="text/javascript" charset="utf-8">
// thedate.x comes from the edit_task view. If this is a new entry, // thedate.x comes from the edit_task view. If this is a new entry,
// thedate won't be present and datepicker will fall back on the default (today). // thedate won't be present and datepicker will fall back on the default (today).
$(document).ready(function(){ $(document).ready(function(){
$('#id_due_date').datepicker({defaultDate: new Date({{thedate.year}}, {{thedate.month}} - 1, {{thedate.day}}),}); $('#id_due_date').datepicker({defaultDate: new Date({{thedate.year}}, {{thedate.month}} - 1, {{thedate.day}}),});
}); });
</script> </script>
{% endblock extrahead %} {% endblock extrahead %}

View file

@ -1,21 +1,10 @@
{% extends "base.html" %} {% extends "todo/base.html" %}
{% block title %}{{ list_title }} to-do items{% endblock %} {% block title %}{{ list_title }} to-do items{% endblock %}
{% block content %} {% block content %}
{# Only admins can delete lists. #} {% if user.is_staff %}
{% ifequal can_del 1 %}
{% if list_killed %}
<p> {{ list.name }} is gone.</p>
<a href="{% url 'todo-lists' %}">Return to lists</a>
{% else %}
<h1>Delete entire list: {{ list.name }} ?</h1> <h1>Delete entire list: {{ list.name }} ?</h1>
<p>Category tally:</p> <p>Category tally:</p>
@ -30,22 +19,14 @@
<form action="" method="post" accept-charset="utf-8"> <form action="" method="post" accept-charset="utf-8">
{% csrf_token %} {% csrf_token %}
<input type="hidden" name="list" value="{{ list.id }}" id="some_name"> <input type="hidden" name="list" value="{{ list.id }}" id="some_name">
<p><input type="submit" name="delete-confirm" value="Do it! &rarr;" class="todo-button"> </p> <p><input type="submit" name="delete-confirm" value="Do it! &rarr;" class="todo-button"> </p>
</form> </form>
<a href="{% url 'todo-incomplete_tasks' list.id list_slug %}">Return to list: {{ list.name }}</a> <a href="{% url 'todo-incomplete_tasks' list.id list_slug %}">Return to list: {{ list.name }}</a>
{% else %}
<p>Sorry, you don't have permission to delete lists. Please contact your group administrator.</p>
{% endif %} {% endif %}
{% else %}
<p>Sorry, you don't have permission to delete lists. Please contact your group administrator.</p>
{% endifequal %}
{% endblock %} {% endblock %}

View file

@ -3,32 +3,25 @@
{% block title %}Search results{% endblock %} {% block title %}Search results{% endblock %}
{% block body_id %}post_search{% endblock %} {% block body_id %}post_search{% endblock %}
{% block content_title %} {% block content_title %}
<h2 class="page_title">Search</h2> <h2 class="page_title">Search</h2>
{% endblock %} {% endblock %}
{% block content %} {% block content %}
{% if found_items %} {% if found_items %}
<h2>{{found_items.count}} search results for term: "{{ query_string }}"</h2> <h2>{{found_items.count}} search results for term: "{{ query_string }}"</h2>
<div class="post_list"> <div class="post_list">
{% for f in found_items %} {% for f in found_items %}
<p><strong><a href="{% url 'todo-task_detail' f.id %}">{{ f.title }}</a></strong><br /> <p><strong><a href="{% url 'todo-task_detail' f.id %}">{{ f.title }}</a></strong><br />
<span class="minor"> <span class="minor">
On list: <a href="{% url 'todo-incomplete_tasks' f.list.id f.list.slug %}">{{ f.list.name }}</a><br /> On list: <a href="{% url 'todo-incomplete_tasks' f.list.id f.list.slug %}">{{ f.list.name }}</a><br />
Assigned to: {{ f.assigned_to }} (created by: {{ f.created_by }})<br /> Assigned to: {{ f.assigned_to }} (created by: {{ f.created_by }})<br />
Complete: {{ f.completed|yesno:"Yes,No" }} Complete: {{ f.completed|yesno:"Yes,No" }}
</span> </span>
</p> </p>
{% endfor %} {% endfor %}
</div> </div>
{% else %} {% else %}
<h2> No results to show, sorry.</h2> <h2> No results to show, sorry.</h2>
{% endif %} {% endif %}
{% endblock %} {% endblock %}

View file

@ -3,9 +3,7 @@
{% block title %}Todo List: {{ list.name }}{% endblock %} {% block title %}Todo List: {{ list.name }}{% endblock %}
{% block content %} {% block content %}
<script type="text/javascript"> <script type="text/javascript">
function order_tasks(data) { function order_tasks(data) {
// The JQuery plugin tableDnD provides a serialize() function which provides the re-ordered // The JQuery plugin tableDnD provides a serialize() function which provides the re-ordered
// data in a list. We pass that list as an object called "data" to a Django view // data in a list. We pass that list as an object called "data" to a Django view
@ -33,26 +31,21 @@
$(this).siblings('#AddTask').slideToggle(); $(this).siblings('#AddTask').slideToggle();
}); });
}); });
</script> </script>
{% if list_slug == "mine" %}
{% ifequal list_slug "mine" %}
<h1>Tasks assigned to {{ request.user }}</h1> <h1>Tasks assigned to {{ request.user }}</h1>
{% else %} {% elif auth_ok %}
{% ifequal auth_ok 1 %}
<h1>Tasks filed under "{{ list.name }}"</h1> <h1>Tasks filed under "{{ list.name }}"</h1>
<p>This list belongs to group {{ list.group }}</p> <p>This list belongs to group {{ list.group }}</p>
{% endifequal %} {% endif %}
{% endifequal %}
{% if auth_ok %}
{% ifequal auth_ok 1 %}
<form action="" method="POST"> <form action="" method="POST">
{% csrf_token %} {% csrf_token %}
{# Only show task adder if viewing a proper list #} {# Only show task adder if viewing a proper list #}
{% ifnotequal list_slug "mine" %} {% if list_slug != "mine" %}
<h2 style="margin-bottom:0px;" id="slideToggle" >&rarr; Click to add task &larr;</h2> <h2 style="margin-bottom:0px;" id="slideToggle" >&rarr; Click to add task &larr;</h2>
<div id="AddTask"> <div id="AddTask">
@ -79,14 +72,11 @@
<input type="hidden" name="created_by" value="{{ request.user.id }}" id="id_created_by"> <input type="hidden" name="created_by" value="{{ request.user.id }}" id="id_created_by">
<input type="hidden" name="list" value="{{ listid }}" id="id_list"> <input type="hidden" name="list" value="{{ listid }}" id="id_list">
<input type="hidden" name="created_date" value="{{ created_date }}" id="id_created_date"> <input type="hidden" name="created_date" value="{{ created_date }}" id="id_created_date">
<p><input type="submit" name="add_task" value="Add task" class="todo-button"></p> <p><input type="submit" name="add_task" value="Add task" class="todo-button"></p>
</div> </div>
{% endif %}
{% endifnotequal %} {% if not view_completed %}
{% ifequal view_completed 0 %}
<h3>Incomplete tasks :: Drag rows to set priorities</h3> <h3>Incomplete tasks :: Drag rows to set priorities</h3>
@ -131,12 +121,12 @@
</tr> </tr>
{% endfor %} {% endfor %}
</table> </table>
<p><input type="submit" name="mark_tasks_done" value="Continue..." class="todo-button"></p> <p><input type="submit" name="mark_tasks_done" value="Continue..." class="todo-button"></p>
<p><a class="todo" href="{% url 'todo-completed_tasks' list_id list_slug %}">View completed tasks</a></p> <p><a class="todo" href="{% url 'todo-completed_tasks' list_id list_slug %}">View completed tasks</a></p>
{% endifequal %}
{% ifequal view_completed 1 %} {% else %}
<h3>Completed tasks</h3> <h3>Completed tasks</h3>
<table border="0" id="tasktable"> <table border="0" id="tasktable">
@ -153,7 +143,6 @@
<th>Del</th> <th>Del</th>
</tr> </tr>
{% for task in completed_list %} {% for task in completed_list %}
<tr> <tr>
<td><input type="checkbox" name="undo_completed_task" value="{{ task.id }}" id="id_undo_completed_task{{ task.id }}"> </td> <td><input type="checkbox" name="undo_completed_task" value="{{ task.id }}" id="id_undo_completed_task{{ task.id }}"> </td>
@ -162,7 +151,6 @@
<td>{{ task.completed_date|date:"m/d/Y" }}</td> <td>{{ task.completed_date|date:"m/d/Y" }}</td>
<td style="text-align:center;">{% if task.note %}&asymp;{% endif %} </td> <td style="text-align:center;">{% if task.note %}&asymp;{% endif %} </td>
<td style="text-align:center;">{% ifnotequal task.comment_set.all.count 0 %}{{ task.comment_set.all.count }}{% endifnotequal %} <td style="text-align:center;">{% ifnotequal task.comment_set.all.count 0 %}{{ task.comment_set.all.count }}{% endifnotequal %}
<td><input type="checkbox" name="del_completed_task" value="{{ task.id }}" id="del_completed_task_{{ task.id }}"> </td> <td><input type="checkbox" name="del_completed_task" value="{{ task.id }}" id="del_completed_task_{{ task.id }}"> </td>
</tr> </tr>
{% endfor %} {% endfor %}
@ -171,13 +159,13 @@
<p><input type="submit" name="deldonetasks" value="Continue..." class="todo-button"></p> <p><input type="submit" name="deldonetasks" value="Continue..." class="todo-button"></p>
</form> </form>
<p><a class="todo" href="{% url 'todo-incomplete_tasks' list_id list_slug %}">View incomplete tasks</a></p> <p><a class="todo" href="{% url 'todo-incomplete_tasks' list_id list_slug %}">View incomplete tasks</a></p>
{% endifequal %} {% endif %}
{% ifequal can_del 1 %} {% if user.is_staff %}
{% ifnotequal list_slug "mine" %} {% if list_slug != "mine" %}
<p><a class="todo" href="{% url 'todo-del_list' list_id list_slug %}">Delete this list</a></p> <p><a class="todo" href="{% url 'todo-del_list' list_id list_slug %}">Delete this list</a></p>
{% endifnotequal %} {% endif %}
{% endifequal %} {% endif %}
{% endifequal %} {% endif %}
{% endblock %} {% endblock %}

View file

@ -17,23 +17,23 @@
}); });
</script> </script>
{% ifequal auth_ok 1 %} {% ifequal auth_ok 1 %}
<h2>{{ task }}</h2> <h2>{{ task }}</h2>
<form action="" method="POST"> <form action="" method="POST">
{% csrf_token %} {% csrf_token %}
<p id="slideToggle" ><strong>&rarr; Click to edit details &larr;</strong></p> <p id="slideToggle" ><strong>&rarr; Click to edit details &larr;</strong></p>
<p><strong>In list:</strong> <a href="{% url 'todo-incomplete_tasks' task.list.id task.list.slug %}" class="showlink">{{ task.list }}</a><br /> <p>
<strong>In list:</strong> <a href="{% url 'todo-incomplete_tasks' task.list.id task.list.slug %}" class="showlink">{{ task.list }}</a><br />
<strong>Assigned to:</strong> {{ task.assigned_to.first_name }} {{ task.assigned_to.last_name }}<br /> <strong>Assigned to:</strong> {{ task.assigned_to.first_name }} {{ task.assigned_to.last_name }}<br />
<strong>Created by:</strong> {{ task.created_by.first_name }} {{ task.created_by.last_name }}<br /> <strong>Created by:</strong> {{ task.created_by.first_name }} {{ task.created_by.last_name }}<br />
<strong>Due date:</strong> {{ task.due_date }}<br /> <strong>Due date:</strong> {{ task.due_date }}<br />
<strong>Completed:</strong> {{ form.completed }}<br /> <strong>Completed:</strong> {{ form.completed }}<br />
</p> </p>
{% if task.note %} {% if task.note %}
<div class="task_note"><strong>Note:</strong> {{ task.note|safe|urlize|linebreaks }}</div> <div class="task_note"><strong>Note:</strong> {{ task.note|safe|urlize|linebreaks }}</div>
{% endif %} {% endif %}
@ -78,12 +78,9 @@
<p><input type="submit" class="todo-button" name="edit_task" value="Edit task"></p> <p><input type="submit" class="todo-button" name="edit_task" value="Edit task"></p>
</div> </div>
<hr /> <hr />
<h3>Add comment</h3> <h3>Add comment</h3>
<textarea name="comment-body"></textarea> <textarea name="comment-body"></textarea>
<p><input class="todo-button"type="submit" value="Submit"></p> <p><input class="todo-button"type="submit" value="Submit"></p>
@ -93,7 +90,11 @@
<div class="task_comments"> <div class="task_comments">
{% for comment in comment_list %} {% for comment in comment_list %}
<p><strong>{{ comment.author.first_name }} {{ comment.author.last_name }}, {{ comment.date|date:"F d Y P" }}</strong> </p> <p>
<strong>{{ comment.author.first_name }} {{ comment.author.last_name }},
{{ comment.date|date:"F d Y P" }}
</strong>
</p>
{{ comment.body|safe|urlize|linebreaks }} {{ comment.body|safe|urlize|linebreaks }}
{% empty %} {% empty %}
<p>No Comments</p> <p>No Comments</p>

View file

@ -7,7 +7,7 @@ urlpatterns = [
url(r'^(?P<list_id>\d{1,4})/(?P<list_slug>[\w-]+)/delete$', views.del_list, name="todo-del_list"), url(r'^(?P<list_id>\d{1,4})/(?P<list_slug>[\w-]+)/delete$', views.del_list, name="todo-del_list"),
url(r'^task/(?P<task_id>\d{1,6})$', views.view_task, name='todo-task_detail'), url(r'^task/(?P<task_id>\d{1,6})$', views.view_task, name='todo-task_detail'),
url(r'^(?P<list_id>\d{1,4})/(?P<list_slug>[\w-]+)$', views.view_list, name='todo-incomplete_tasks'), url(r'^(?P<list_id>\d{1,4})/(?P<list_slug>[\w-]+)$', views.view_list, name='todo-incomplete_tasks'),
url(r'^(?P<list_id>\d{1,4})/(?P<list_slug>[\w-]+)/completed$', views.view_list, {'view_completed': 1}, url(r'^(?P<list_id>\d{1,4})/(?P<list_slug>[\w-]+)/completed$', views.view_list, {'view_completed': True},
name='todo-completed_tasks'), name='todo-completed_tasks'),
url(r'^add_list/$', views.add_list, name="todo-add_list"), url(r'^add_list/$', views.add_list, name="todo-add_list"),
url(r'^search-post/$', views.search_post, name="todo-search-post"), url(r'^search-post/$', views.search_post, name="todo-search-post"),

View file

@ -1,24 +1,22 @@
from django.shortcuts import render_to_response import datetime
from todo.models import Item, List, Comment
from todo.forms import AddListForm, AddItemForm, EditItemForm, AddExternalItemForm, SearchForm from django.contrib.auth.decorators import user_passes_test, login_required
from todo import settings
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.shortcuts import get_object_or_404 from django.contrib import messages
from django.template import RequestContext
from django.http import HttpResponseRedirect, HttpResponse
from django.core.urlresolvers import reverse
from django.contrib.sites.models import Site from django.contrib.sites.models import Site
from django.template.loader import render_to_string
from django.core.mail import send_mail from django.core.mail import send_mail
from django.contrib.auth.decorators import user_passes_test from django.core.urlresolvers import reverse
from django.db import IntegrityError from django.db import IntegrityError
from django.db.models import Q from django.db.models import Q
from django.contrib import messages from django.http import HttpResponseRedirect, HttpResponse
from django.shortcuts import get_object_or_404, render_to_response
from django.template import RequestContext
from django.template.loader import render_to_string
from django.views.decorators.csrf import csrf_exempt from django.views.decorators.csrf import csrf_exempt
from django.contrib.auth.decorators import login_required
from todo import settings
import datetime from todo.forms import AddListForm, AddItemForm, EditItemForm, AddExternalItemForm, SearchForm
from todo.models import Item, List, Comment
# Need for links in email templates # Need for links in email templates
current_site = Site.objects.get_current() current_site = Site.objects.get_current()
@ -47,17 +45,15 @@ def list_lists(request):
if group_count == 0: if group_count == 0:
messages.error(request, "You do not yet belong to any groups. Ask your administrator to add you to one.") messages.error(request, "You do not yet belong to any groups. Ask your administrator to add you to one.")
# Only show lists to the user that belong to groups they are members of.
# Superusers see all lists # Superusers see all lists
if request.user.is_superuser: if request.user.is_superuser:
list_list = List.objects.all().order_by('group', 'name') list_list = List.objects.all().order_by('group', 'name')
else: else:
list_list = List.objects.filter(group__in=request.user.groups.all()).order_by('group', 'name') list_list = List.objects.filter(group__in=request.user.groups.all()).order_by('group', 'name')
# Count everything
list_count = list_list.count() list_count = list_list.count()
# Note admin users see all lists, so count shouldn't filter by just lists the admin belongs to # superusers see all lists, so count shouldn't filter by just lists the admin belongs to
if request.user.is_superuser: if request.user.is_superuser:
item_count = Item.objects.filter(completed=0).count() item_count = Item.objects.filter(completed=0).count()
else: else:
@ -71,25 +67,13 @@ def del_list(request, list_id, list_slug):
""" """
Delete an entire list. Danger Will Robinson! Only staff members should be allowed to access this view. Delete an entire list. Danger Will Robinson! Only staff members should be allowed to access this view.
""" """
if request.user.is_staff:
can_del = 1
# Get this list's object (to derive list.name, list.id, etc.)
list = get_object_or_404(List, slug=list_slug) list = get_object_or_404(List, slug=list_slug)
# If delete confirmation is in the POST, delete all items in the list, then kill the list itself
if request.method == 'POST': if request.method == 'POST':
# Can the items
del_items = Item.objects.filter(list=list.id)
for del_item in del_items:
del_item.delete()
# Kill the list
del_list = List.objects.get(id=list.id) del_list = List.objects.get(id=list.id)
del_list.delete() messages.success(request, "{list_name} is gone.".format(list_name=del_list.name))
del_list.delete() # Delete after creating message, or message fails.
# A var to send to the template so we can show the right thing return HttpResponseRedirect(reverse('todo-lists'))
list_killed = 1
else: else:
item_count_done = Item.objects.filter(list=list.id, completed=1).count() item_count_done = Item.objects.filter(list=list.id, completed=1).count()
item_count_undone = Item.objects.filter(list=list.id, completed=0).count() item_count_undone = Item.objects.filter(list=list.id, completed=0).count()
@ -99,82 +83,79 @@ def del_list(request, list_id, list_slug):
@user_passes_test(check_user_allowed) @user_passes_test(check_user_allowed)
def view_list(request, list_id=0, list_slug=None, view_completed=0): def view_list(request, list_id=0, list_slug=None, view_completed=False):
""" """
Display and manage items in a task list Display and manage items in a list.
""" """
# Make sure the accessing user has permission to view this list. # Make sure the accessing user has permission to view this list.
# Always authorize the "mine" view. Admins can view/edit all lists. # Always authorize the "mine" view. Admins can view/edit all lists.
if list_slug == "mine" or list_slug == "recent-add" or list_slug == "recent-complete": if list_slug == "mine" or list_slug == "recent-add" or list_slug == "recent-complete":
auth_ok = 1 auth_ok = 1
else: else:
list = get_object_or_404(List, slug=list_slug) list = get_object_or_404(List, slug=list_slug)
listid = list.id listid = list.id
# Check whether current user is a member of the group this list belongs to.
if list.group in request.user.groups.all() or request.user.is_staff or list_slug == "mine": if list.group in request.user.groups.all() or request.user.is_staff or list_slug == "mine":
auth_ok = 1 # User is authorized for this view auth_ok = True # User is authorized for this view
else: # User does not belong to the group this list is attached to else: # User does not belong to the group this list is attached to
messages.error(request, "You do not have permission to view/edit this list.") messages.error(request, "You do not have permission to view/edit this list.")
# First check for items in the mark_done POST array. If present, change # Check for items in the mark_done POST array. If present, change status to complete.
# their status to complete.
if request.POST.getlist('mark_done'): if request.POST.getlist('mark_done'):
done_items = request.POST.getlist('mark_done') done_items = request.POST.getlist('mark_done')
# Iterate through array of done items and update its representation in the model for item in done_items:
for thisitem in done_items: i = Item.objects.get(id=item)
p = Item.objects.get(id=thisitem) i.completed = 1
p.completed = 1 i.completed_date = datetime.datetime.now()
p.completed_date = datetime.datetime.now() i.save()
p.save() messages.success(request, "Item \"{i}\" marked complete.".format(i=i.title))
messages.success(request, "Item \"%s\" marked complete." % p.title)
# Undo: Set completed items back to incomplete # Undo: Set completed items back to incomplete
if request.POST.getlist('undo_completed_task'): if request.POST.getlist('undo_completed_task'):
undone_items = request.POST.getlist('undo_completed_task') undone_items = request.POST.getlist('undo_completed_task')
for thisitem in undone_items: for item in undone_items:
p = Item.objects.get(id=thisitem) i = Item.objects.get(id=item)
p.completed = 0 i.completed = False
p.save() i.save()
messages.success(request, "Previously completed task \"%s\" marked incomplete." % p.title) messages.success(request, "Previously completed task \"{i}\" marked incomplete.".format(i=i.title))
# And delete any requested items # And delete any requested items
if request.POST.getlist('del_task'): if request.POST.getlist('del_task'):
deleted_items = request.POST.getlist('del_task') deleted_items = request.POST.getlist('del_task')
for thisitem in deleted_items: for item in deleted_items:
p = Item.objects.get(id=thisitem) i = Item.objects.get(id=item)
p.delete() i.delete()
messages.success(request, "Item \"%s\" deleted." % p.title) messages.success(request, "Item \"{i}\" deleted.".format(i=i.title))
# And delete any *already completed* items # Delete any already-completed items
if request.POST.getlist('del_completed_task'): if request.POST.getlist('del_completed_task'):
deleted_items = request.POST.getlist('del_completed_task') deleted_items = request.POST.getlist('del_completed_task')
for thisitem in deleted_items: for item in deleted_items:
p = Item.objects.get(id=thisitem) i = Item.objects.get(id=item)
p.delete() i.delete()
messages.success(request, "Deleted previously completed item \"%s\"." % p.title) messages.success(request, "Deleted previously completed item \"{i}\".".format(i=i.title))
thedate = datetime.datetime.now() thedate = datetime.datetime.now()
created_date = "%s-%s-%s" % (thedate.year, thedate.month, thedate.day) created_date = "%s-%s-%s" % (thedate.year, thedate.month, thedate.day)
# Get list of items with this list ID, or filter on items assigned to me, or recently added/completed # Get list of items with this list ID, or filter on items assigned to me, or recently added/completed
if list_slug == "mine": if list_slug == "mine":
task_list = Item.objects.filter(assigned_to=request.user, completed=0) task_list = Item.objects.filter(assigned_to=request.user, completed=False)
completed_list = Item.objects.filter(assigned_to=request.user, completed=1) completed_list = Item.objects.filter(assigned_to=request.user, completed=True)
elif list_slug == "recent-add": elif list_slug == "recent-add":
# We'll assume this only includes uncompleted items to avoid confusion.
# Only show items in lists that are in groups that the current user is also in. # Only show items in lists that are in groups that the current user is also in.
task_list = Item.objects.filter(list__group__in=(request.user.groups.all()), # Assume this only includes uncompleted items to avoid confusion.
completed=0).order_by('-created_date')[:50] task_list = Item.objects.filter(
# completed_list = Item.objects.filter(assigned_to=request.user, completed=1) list__group__in=(request.user.groups.all()),
completed=False).order_by('-created_date')[:50]
elif list_slug == "recent-complete": elif list_slug == "recent-complete":
# Only show items in lists that are in groups that the current user is also in. # Only show items in lists that are in groups that the current user is also in.
task_list = Item.objects.filter(list__group__in=request.user.groups.all(), task_list = Item.objects.filter(
completed=1).order_by('-completed_date')[:50] list__group__in=request.user.groups.all(),
# completed_list = Item.objects.filter(assigned_to=request.user, completed=1) completed=True).order_by('-completed_date')[:50]
else: else:
task_list = Item.objects.filter(list=list.id, completed=0) task_list = Item.objects.filter(list=list.id, completed=0)
@ -187,38 +168,35 @@ def view_list(request, list_id=0, list_slug=None, view_completed=0):
}) })
if form.is_valid(): if form.is_valid():
# Save task first so we have a db object to play with
new_task = form.save() new_task = form.save()
# Send email alert only if the Notify checkbox is checked AND the assignee is not the same as the submittor # Send email alert only if Notify checkbox is checked AND assignee is not same as the submitter
# Email subect and body format are handled by templates
if "notify" in request.POST: if "notify" in request.POST:
if new_task.assigned_to != request.user: if new_task.assigned_to != request.user:
# Send email # Send email
email_subject = render_to_string("todo/email/assigned_subject.txt", {'task': new_task}) email_subject = render_to_string("todo/email/assigned_subject.txt", {'task': new_task})
email_body = render_to_string("todo/email/assigned_body.txt", email_body = render_to_string(
"todo/email/assigned_body.txt",
{'task': new_task, 'site': current_site, }) {'task': new_task, 'site': current_site, })
try: try:
send_mail(email_subject, email_body, new_task.created_by.email, [new_task.assigned_to.email], send_mail(
fail_silently=False) email_subject, email_body, new_task.created_by.email,
[new_task.assigned_to.email], fail_silently=False)
except: except:
messages.error(request, "Task saved but mail not sent. Contact your administrator.") messages.error(request, "Task saved but mail not sent. Contact your administrator.")
messages.success(request, "New task \"%s\" has been added." % new_task.title) messages.success(request, "New task \"{t}\" has been added.".format(t=new_task.title))
return HttpResponseRedirect(request.path) return HttpResponseRedirect(request.path)
else: else:
# We don't allow adding a task on the "mine" view # Don't allow adding new tasks on some views
if list_slug != "mine" and list_slug != "recent-add" and list_slug != "recent-complete": if list_slug != "mine" and list_slug != "recent-add" and list_slug != "recent-complete":
form = AddItemForm(list, initial={ form = AddItemForm(list, initial={
'assigned_to': request.user.id, 'assigned_to': request.user.id,
'priority': 999, 'priority': 999,
}) })
if request.user.is_staff:
can_del = 1
return render_to_response('todo/view_list.html', locals(), context_instance=RequestContext(request)) return render_to_response('todo/view_list.html', locals(), context_instance=RequestContext(request))
@ -230,13 +208,13 @@ def view_task(request, task_id):
task = get_object_or_404(Item, pk=task_id) task = get_object_or_404(Item, pk=task_id)
comment_list = Comment.objects.filter(task=task_id) comment_list = Comment.objects.filter(task=task_id)
# Before doing anything, make sure the accessing user has permission to view this item. # Ensure user has permission to view item.
# Determine the group this task belongs to, and check whether current user is a member of that group. # Get the group this task belongs to, and check whether current user is a member of that group.
# Admins can edit all tasks. # Admins can edit all tasks.
if task.list.group in request.user.groups.all() or request.user.is_staff: if task.list.group in request.user.groups.all() or request.user.is_staff:
auth_ok = True
auth_ok = 1
if request.POST: if request.POST:
form = EditItemForm(request.POST, instance=task) form = EditItemForm(request.POST, instance=task)
@ -254,9 +232,10 @@ def view_task(request, task_id):
# And email comment to all people who have participated in this thread. # And email comment to all people who have participated in this thread.
email_subject = render_to_string("todo/email/assigned_subject.txt", {'task': task}) email_subject = render_to_string("todo/email/assigned_subject.txt", {'task': task})
email_body = render_to_string("todo/email/newcomment_body.txt", email_body = render_to_string(
{'task': task, 'body': request.POST['comment-body'], "todo/email/newcomment_body.txt",
'site': current_site, 'user': request.user}) {'task': task, 'body': request.POST['comment-body'], 'site': current_site, 'user': request.user}
)
# Get list of all thread participants - task creator plus everyone who has commented on it. # Get list of all thread participants - task creator plus everyone who has commented on it.
recip_list = [] recip_list = []
@ -264,14 +243,11 @@ def view_task(request, task_id):
commenters = Comment.objects.filter(task=task) commenters = Comment.objects.filter(task=task)
for c in commenters: for c in commenters:
recip_list.append(c.author.email) recip_list.append(c.author.email)
# Eliminate duplicate emails with the Python set() function recip_list = set(recip_list) # Eliminate duplicates
recip_list = set(recip_list)
# Send message
try: try:
send_mail(email_subject, email_body, task.created_by.email, recip_list, fail_silently=False) send_mail(email_subject, email_body, task.created_by.email, recip_list, fail_silently=False)
messages.success(request, "Comment sent to thread participants.") messages.success(request, "Comment sent to thread participants.")
except: except:
messages.error(request, "Comment saved but mail not sent. Contact your administrator.") messages.error(request, "Comment saved but mail not sent. Contact your administrator.")
@ -300,14 +276,13 @@ def reorder_tasks(request):
# First item in received list is always empty - remove it # First item in received list is always empty - remove it
del newtasklist[0] del newtasklist[0]
# Items arrive in order, so all we need to do is increment up from one, saving # Re-prioritize each item in list
# "i" as the new priority for the current object.
i = 1 i = 1
for t in newtasklist: for t in newtasklist:
newitem = Item.objects.get(pk=t) newitem = Item.objects.get(pk=t)
newitem.priority = i newitem.priority = i
newitem.save() newitem.save()
i = i + 1 i += 1
# All views must return an httpresponse of some kind ... without this we get # All views must return an httpresponse of some kind ... without this we get
# error 500s in the log even though things look peachy in the browser. # error 500s in the log even though things look peachy in the browser.
@ -326,19 +301,17 @@ def external_add(request):
form = AddExternalItemForm(request.POST) form = AddExternalItemForm(request.POST)
if form.is_valid(): if form.is_valid():
# Don't commit the save until we've added in the fields we need to set
item = form.save(commit=False) item = form.save(commit=False)
item.list_id = settings.DEFAULT_LIST_ID item.list_id = settings.DEFAULT_LIST_ID
item.created_by = request.user item.created_by = request.user
item.assigned_to = User.objects.get(username=settings.DEFAULT_ASSIGNEE) item.assigned_to = User.objects.get(username=settings.DEFAULT_ASSIGNEE)
item.save() item.save()
# Send email
email_subject = render_to_string("todo/email/assigned_subject.txt", {'task': item.title}) email_subject = render_to_string("todo/email/assigned_subject.txt", {'task': item.title})
email_body = render_to_string("todo/email/assigned_body.txt", {'task': item, 'site': current_site, }) email_body = render_to_string("todo/email/assigned_body.txt", {'task': item, 'site': current_site, })
try: try:
send_mail(email_subject, email_body, item.created_by.email, [item.assigned_to.email], send_mail(
fail_silently=False) email_subject, email_body, item.created_by.email, [item.assigned_to.email, ], fail_silently=False)
except: except:
messages.error(request, "Task saved but mail not sent. Contact your administrator.") messages.error(request, "Task saved but mail not sent. Contact your administrator.")
@ -364,7 +337,8 @@ def add_list(request):
messages.success(request, "A new list has been added.") messages.success(request, "A new list has been added.")
return HttpResponseRedirect(request.path) return HttpResponseRedirect(request.path)
except IntegrityError: except IntegrityError:
messages.error(request, messages.error(
request,
"There was a problem saving the new list. " "There was a problem saving the new list. "
"Most likely a list with the same name in the same group already exists.") "Most likely a list with the same name in the same group already exists.")
else: else:
@ -406,7 +380,7 @@ def search(request):
else: else:
# What if they selected the "completed" toggle but didn't type in a query string? # What if they selected the "completed" toggle but didn't type in a query string?
# In that case we still need found_items in a queryset so it can be "excluded" below. # We still need found_items in a queryset so it can be "excluded" below.
found_items = Item.objects.all() found_items = Item.objects.all()
if 'inc_complete' in request.GET: if 'inc_complete' in request.GET:
@ -416,6 +390,7 @@ def search(request):
query_string = None query_string = None
found_items = None found_items = None
return render_to_response('todo/search_results.html', return render_to_response(
'todo/search_results.html',
{'query_string': query_string, 'found_items': found_items}, {'query_string': query_string, 'found_items': found_items},
context_instance=RequestContext(request)) context_instance=RequestContext(request))