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,70 +4,59 @@
{% 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 %}
<div class="task_note"><strong>Note:</strong> {{ task.note|safe|urlize|linebreaks }}</div>
{% endif %}
{% if task.note %} <div id="TaskEdit">
<div class="task_note"><strong>Note:</strong> {{ task.note|safe|urlize|linebreaks }}</div> <h3>File Trouble Ticket</h3>
{% endif %} <p>Trouble with a computer or other technical system at the J-School? <br />
Use this form to report the difficulty - we'll get right back to you. </p>
<div id="TaskEdit"> {% if form.errors %}
<h3>File Trouble Ticket</h3>
<p>Trouble with a computer or other technical system at the J-School? <br />
Use this form to report the difficulty - we'll get right back to you. </p>
{% if form.errors %} {% for error in form.errors %}
<ul class="errorlist">
<li><strong>The {{ error|escape }} field is required.</strong></li>
</ul>
{% endfor %}
<br />
{% for error in form.errors %} {% endif %}
<ul class="errorlist">
<li><strong>The {{ error|escape }} field is required.</strong></li>
</ul>
{% endfor %}
<br />
{% endif %} <table>
{{ form.management_form }}
{{ form.id }}
<tr>
<td>Summary:</td>
<td>{{ form.title }} <br />
Include the workstation number in your summary, e.g. <br />
"Radio Lab # 4: Purple smoke pouring out the back."
</td>
</tr>
<table> <tr>
{{ form.management_form }} <td valign="top">Note:</td>
{{ form.id }} <td valign="top">{{ form.note }}<br />
Please describe the problem.
<tr> </td>
<td>Summary:</td> </tr>
<td>{{ form.title }} <br />
Include the workstation number in your summary, e.g. <br />
"Radio Lab # 4: Purple smoke pouring out the back."
</td>
</tr>
<tr>
<td valign="top">Note:</td>
<td valign="top">{{ form.note }}<br />
Please describe the problem. </td>
</tr>
<tr>
<td>Priority:</td>
<td>{{ form.priority }} <br />
Enter a number between 1 and 5, <br />
where 5 is highest ("Computer is on fire = True").
</td>
</tr>
</table>
<p><input type="submit" class="todo-button" name="add_task" value="Submit"></p>
</div>
<tr>
<td>Priority:</td>
<td>{{ form.priority }} <br />
Enter a number between 1 and 5, <br />
where 5 is highest ("Computer is on fire = True").
</td>
</tr>
</table>
<p><input type="submit" class="todo-button" name="add_task" value="Submit"></p>
</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,51 +1,32 @@
{% 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 %} <h1>Delete entire list: {{ list.name }} ?</h1>
<p>Category tally:</p>
{% if list_killed %} <ul>
<li>Incomplete: {{ item_count_undone }} </li>
<li>Complete: {{ item_count_done }} </li>
<li><strong>Total: {{ item_count_total }}</strong> </li>
</ul>
<p> {{ list.name }} is gone.</p> <p> ... all of which will be irretrievably <strong>blown away</strong>. Are you sure you want to do that?</p>
<a href="{% url 'todo-lists' %}">Return to lists</a> <form action="" method="post" accept-charset="utf-8">
{% csrf_token %}
{% else %} <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>
<h1>Delete entire list: {{ list.name }} ?</h1> </form>
<p>Category tally:</p>
<ul>
<li>Incomplete: {{ item_count_undone }} </li>
<li>Complete: {{ item_count_done }} </li>
<li><strong>Total: {{ item_count_total }}</strong> </li>
</ul>
<p> ... all of which will be irretrievably <strong>blown away</strong>. Are you sure you want to do that?</p>
<form action="" method="post" accept-charset="utf-8">
{% csrf_token %}
<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>
</form>
<a href="{% url 'todo-incomplete_tasks' list.id list_slug %}">Return to list: {{ list.name }}</a>
{% endif %}
<a href="{% url 'todo-incomplete_tasks' list.id list_slug %}">Return to list: {{ list.name }}</a>
{% else %} {% else %}
<p>Sorry, you don't have permission to delete lists. Please contact your group administrator.</p> <p>Sorry, you don't have permission to delete lists. Please contact your group administrator.</p>
{% endif %}
{% 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 %}
<p><strong><a href="{% url 'todo-task_detail' f.id %}">{{ f.title }}</a></strong><br />
{% for f in found_items %} <span class="minor">
<p><strong><a href="{% url 'todo-task_detail' f.id %}">{{ f.title }}</a></strong><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 />
<span class="minor"> Complete: {{ f.completed|yesno:"Yes,No" }}
On list: <a href="{% url 'todo-incomplete_tasks' f.list.id f.list.slug %}">{{ f.list.name }}</a><br /> </span>
Assigned to: {{ f.assigned_to }} (created by: {{ f.created_by }})<br /> </p>
Complete: {{ f.completed|yesno:"Yes,No" }} {% endfor %}
</span> </div>
{% else %}
</p> <h2> No results to show, sorry.</h2>
{% endfor %} {% endif %}
</div> {% endblock %}
{% else %}
<h2> No results to show, sorry.</h2>
{% endif %}
{% endblock %}

View file

@ -3,181 +3,169 @@
{% 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) {
// 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
// to save the re-ordered data into the database.
function order_tasks(data) { $.post("{% url 'todo-reorder_tasks' %}", data, "json");
// The JQuery plugin tableDnD provides a serialize() function which provides the re-ordered return false;
// data in a list. We pass that list as an object called "data" to a Django view };
// to save the re-ordered data into the database.
$.post("{% url 'todo-reorder_tasks' %}", data, "json"); $(document).ready(function() {
return false; // Initialise the task table for drag/drop re-ordering
}; $("#tasktable").tableDnD();
$(document).ready(function() { $('#tasktable').tableDnD({
// Initialise the task table for drag/drop re-ordering onDrop: function(table, row) {
$("#tasktable").tableDnD(); order_tasks($.tableDnD.serialize());
}
});
$('#tasktable').tableDnD({ // Initially hide the Add Task form
onDrop: function(table, row) { $('#AddTask').hide();
order_tasks($.tableDnD.serialize());
} // toggle slide to show the Add Task form when link clicked
$('#slideToggle').click(function(){
$(this).siblings('#AddTask').slideToggle();
});
}); });
// Initially hide the Add Task form
$('#AddTask').hide();
// toggle slide to show the Add Task form when link clicked
$('#slideToggle').click(function(){
$(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> {% endif %}
{% endifequal %}
{% 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">
<table class="nocolor" border="0" cellspacing="5" cellpadding="5"> <table class="nocolor" border="0" cellspacing="5" cellpadding="5">
<tr> <tr>
<td>{{ form.title.errors }}</td> <td>{{ form.title.errors }}</td>
<td>{{ form.due_date.errors }}</td> <td>{{ form.due_date.errors }}</td>
</tr> </tr>
<tr> <tr>
<td><label for="id_title">Task:</label> {{ form.title }}</td> <td><label for="id_title">Task:</label> {{ form.title }}</td>
<td><label for="id_due_date">Due date:</label> {{ form.due_date }}</td> <td><label for="id_due_date">Due date:</label> {{ form.due_date }}</td>
<td><label for="id_assigned">Assign to:</label> {{ form.assigned_to }}</td> <td><label for="id_assigned">Assign to:</label> {{ form.assigned_to }}</td>
<td><label for="id_notify">Notify*:</label> <input type="checkbox" checked="checked" name="notify" value="1" id="notify"></td> <td><label for="id_notify">Notify*:</label> <input type="checkbox" checked="checked" name="notify" value="1" id="notify"></td>
</tr> </tr>
<tr> <tr>
<td><label for="id_note">Note:</label> <td><label for="id_note">Note:</label>
{{ form.note }} {{ form.note }}
<p class="minor">*Email notifications will only be sent if task is assigned to someone besides yourself.</p> <p class="minor">*Email notifications will only be sent if task is assigned to someone besides yourself.</p>
</td> </td>
</tr> </tr>
</table> </table>
<input type="hidden" name="priority" value="999" id="id_priority"> <input type="hidden" name="priority" value="999" id="id_priority">
<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>
</div>
{% endif %}
<p><input type="submit" name="add_task" value="Add task" class="todo-button"></p> {% if not view_completed %}
</div>
{% endifnotequal %} <h3>Incomplete tasks :: Drag rows to set priorities</h3>
<table border="0" id="tasktable">
<tr>
<th>Done</th>
<th>Task</th>
<th>Created</th>
<th>Due on</th>
<th>Owner</th>
<th>Assigned</th>
<th>Note</th>
<th>Comm</th>
{% ifequal view_completed 0 %} {% ifequal list_slug "mine" %}
<th>List</th>
{% endifequal %}
<h3>Incomplete tasks :: Drag rows to set priorities</h3> <th>Del</th>
</tr>
{% for task in task_list %}
<tr id="{{ task.id }}">
<td><input type="checkbox" name="mark_done" value="{{ task.id }}" id="mark_done_{{ task.id }}"> </td>
<td><a href="{% url 'todo-task_detail' task.id %}">{{ task.title|truncatewords:20 }}</a></td>
<td>{{ task.created_date|date:"m/d/Y" }}</td>
<td>
{% if task.overdue_status %}<span class="overdue">{% endif %}
{{ task.due_date|date:"m/d/Y" }}
{% if task.overdue_status %}</span>{% endif %}
</td>
<td>{{ task.created_by }}</td>
<td>{{ task.assigned_to }}</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 %}
<table border="0" id="tasktable"> </td>
<tr> {% ifequal list_slug "mine" %}
<th>Done</th> <td><a href="{% url 'todo-incomplete_tasks' task.list.id task.list.slug %}">{{ task.list }}</a></td>
<th>Task</th> {% endifequal %}
<th>Created</th>
<th>Due on</th>
<th>Owner</th>
<th>Assigned</th>
<th>Note</th>
<th>Comm</th>
{% ifequal list_slug "mine" %} <td><input type="checkbox" name="del_task" value="{{ task.id }}" id="del_task_{{ task.id }}"> </td>
<th>List</th> </tr>
{% endifequal %} {% endfor %}
</table>
<th>Del</th> <p><input type="submit" name="mark_tasks_done" value="Continue..." class="todo-button"></p>
</tr> <p><a class="todo" href="{% url 'todo-completed_tasks' list_id list_slug %}">View completed tasks</a></p>
{% for task in task_list %}
<tr id="{{ task.id }}">
<td><input type="checkbox" name="mark_done" value="{{ task.id }}" id="mark_done_{{ task.id }}"> </td>
<td><a href="{% url 'todo-task_detail' task.id %}">{{ task.title|truncatewords:20 }}</a></td>
<td>{{ task.created_date|date:"m/d/Y" }}</td>
<td>
{% if task.overdue_status %}<span class="overdue">{% endif %}
{{ task.due_date|date:"m/d/Y" }}
{% if task.overdue_status %}</span>{% endif %}
</td>
<td>{{ task.created_by }}</td>
<td>{{ task.assigned_to }}</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> {% else %}
{% ifequal list_slug "mine" %}
<td><a href="{% url 'todo-incomplete_tasks' task.list.id task.list.slug %}">{{ task.list }}</a></td>
{% endifequal %}
<td><input type="checkbox" name="del_task" value="{{ task.id }}" id="del_task_{{ task.id }}"> </td> <h3>Completed tasks</h3>
</tr>
{% endfor %}
</table>
<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> <table border="0" id="tasktable">
{% endifequal %} <tr>
<th>Undo</th>
<th>Task</th>
<th>Created</th>
<th>Completed on</th>
<th>Note</th>
<th>Comm</th>
{% ifequal list_slug "mine" %}
<th>List</th>
{% endifequal %}
<th>Del</th>
</tr>
{% ifequal view_completed 1 %} {% for task in completed_list %}
<h3>Completed tasks</h3> <tr>
<td><input type="checkbox" name="undo_completed_task" value="{{ task.id }}" id="id_undo_completed_task{{ task.id }}"> </td>
<td><a href="{% url 'todo-task_detail' task.id %}">{{ task.title|truncatewords:20 }}</a></td>
<td>{{ task.created_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;">{% 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>
</tr>
{% endfor %}
<table border="0" id="tasktable"> </table>
<tr> <p><input type="submit" name="deldonetasks" value="Continue..." class="todo-button"></p>
<th>Undo</th> </form>
<th>Task</th> <p><a class="todo" href="{% url 'todo-incomplete_tasks' list_id list_slug %}">View incomplete tasks</a></p>
<th>Created</th> {% endif %}
<th>Completed on</th>
<th>Note</th>
<th>Comm</th>
{% ifequal list_slug "mine" %}
<th>List</th>
{% endifequal %}
<th>Del</th>
</tr>
{% if user.is_staff %}
{% if list_slug != "mine" %}
<p><a class="todo" href="{% url 'todo-del_list' list_id list_slug %}">Delete this list</a></p>
{% endif %}
{% endif %}
{% for task in completed_list %} {% endif %}
<tr> {% endblock %}
<td><input type="checkbox" name="undo_completed_task" value="{{ task.id }}" id="id_undo_completed_task{{ task.id }}"> </td>
<td><a href="{% url 'todo-task_detail' task.id %}">{{ task.title|truncatewords:20 }}</a></td>
<td>{{ task.created_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;">{% 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>
</tr>
{% endfor %}
</table>
<p><input type="submit" name="deldonetasks" value="Continue..." class="todo-button"></p>
</form>
<p><a class="todo" href="{% url 'todo-incomplete_tasks' list_id list_slug %}">View incomplete tasks</a></p>
{% endifequal %}
{% ifequal can_del 1 %}
{% ifnotequal list_slug "mine" %}
<p><a class="todo" href="{% url 'todo-del_list' list_id list_slug %}">Delete this list</a></p>
{% endifnotequal %}
{% endifequal %}
{% endifequal %}
{% endblock %}

View file

@ -17,73 +17,70 @@
}); });
</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><strong>In list:</strong> <a href="{% url 'todo-incomplete_tasks' task.list.id task.list.slug %}" class="showlink">{{ task.list }}</a><br /> <p id="slideToggle" ><strong>&rarr; Click to edit details &larr;</strong></p>
<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>Due date:</strong> {{ task.due_date }}<br />
<strong>Completed:</strong> {{ form.completed }}<br />
</p>
<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>Created by:</strong> {{ task.created_by.first_name }} {{ task.created_by.last_name }}<br />
<strong>Due date:</strong> {{ task.due_date }}<br />
<strong>Completed:</strong> {{ form.completed }}<br />
</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 %}
<div id="TaskEdit"> <div id="TaskEdit">
<h3>Edit Task</h3> <h3>Edit Task</h3>
<table> <table>
{{ form.management_form }} {{ form.management_form }}
{{ form.id }} {{ form.id }}
<tr> <tr>
<td>Title:</td> <td>Title:</td>
<td>{{ form.title }} </td> <td>{{ form.title }} </td>
</tr> </tr>
<tr> <tr>
<td>List:</td> <td>List:</td>
<td>{{ form.list }} </td> <td>{{ form.list }} </td>
</tr> </tr>
<tr> <tr>
<td>Due:</td> <td>Due:</td>
<td>{{ form.due_date }} </td> <td>{{ form.due_date }} </td>
</tr> </tr>
<tr> <tr>
<td>Assigned to:</td> <td>Assigned to:</td>
<td>{{ form.assigned_to }} </td> <td>{{ form.assigned_to }} </td>
</tr> </tr>
<tr> <tr>
<td valign="top">Note:</td> <td valign="top">Note:</td>
<td>{{ form.note }} </td> <td>{{ form.note }} </td>
</tr> </tr>
<tr> <tr>
<td>Priority:</td> <td>Priority:</td>
<td>{{ form.priority }} </td> <td>{{ form.priority }} </td>
</tr> </tr>
</table> </table>
<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>
@ -92,12 +89,16 @@
<h3>Comments on this task</h3> <h3>Comments on this task</h3>
<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>
{{ comment.body|safe|urlize|linebreaks }} <strong>{{ comment.author.first_name }} {{ comment.author.last_name }},
{% empty %} {{ comment.date|date:"F d Y P" }}
<p>No Comments</p> </strong>
{% endfor %} </p>
{{ comment.body|safe|urlize|linebreaks }}
{% empty %}
<p>No Comments</p>
{% endfor %}
</div> </div>
{% endifequal %} {% endifequal %}

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(
{'task': new_task, 'site': current_site, }) "todo/email/assigned_body.txt",
{'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,9 +337,10 @@ 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(
"There was a problem saving the new list. " request,
"Most likely a list with the same name in the same group already exists.") "There was a problem saving the new list. "
"Most likely a list with the same name in the same group already exists.")
else: else:
if request.user.groups.all().count() == 1: if request.user.groups.all().count() == 1:
form = AddListForm(request.user, initial={"group": request.user.groups.all()[0]}) form = AddListForm(request.user, initial={"group": request.user.groups.all()[0]})
@ -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(
{'query_string': query_string, 'found_items': found_items}, 'todo/search_results.html',
context_instance=RequestContext(request)) {'query_string': query_string, 'found_items': found_items},
context_instance=RequestContext(request))