Enable task edition

This commit is contained in:
Thierry Carrez 2013-07-05 14:30:19 +02:00
parent 76aaaef12d
commit da321c1046
7 changed files with 128 additions and 13 deletions

View File

@ -12,6 +12,9 @@
.sidebar-nav {
padding: 9px 0;
}
.after-buttongroup {
padding-top: 10px;
}
@media (max-width: 980px) {
/* Enable use of floated navbar text */

View File

@ -29,3 +29,6 @@ class Milestone(models.Model):
name = models.CharField(max_length=50)
series = models.ForeignKey(Series)
active = models.BooleanField(default=True)
class Meta:
ordering = ['name']

View File

@ -38,7 +38,7 @@ class Story(models.Model):
class Task(models.Model):
STATUS_TYPES = (
TASK_STATUSES = (
('T', 'Todo'),
('R', 'In review'),
('L', 'Landed'),
@ -48,7 +48,7 @@ class Task(models.Model):
project = models.ForeignKey(Project)
series = models.ForeignKey(Series)
assignee = models.ForeignKey(User)
status = models.CharField(max_length=1, choices=STATUS_TYPES)
status = models.CharField(max_length=1, choices=TASK_STATUSES)
milestone = models.ForeignKey(Milestone)

View File

@ -1,6 +1,6 @@
{% extends "stories.base.html" %}
{% load markup %}
{% load storypriofilters %}
{% load storyviewfilters %}
{% block extranav %}
<div class="well sidebar-nav">
<ul class="nav nav-list">
@ -40,15 +40,15 @@
</thead>
<tbody>
{% for task in story.task_set.all %}
<tr class="success">
<tr class="{{ task.status|taskcolor }}">
<td>{{ task.title }}</td>
<td>{{ task.project.title }}</td>
<td>{{ task.series.name }}</td>
<td>{{ task.assignee.username }}</td>
<td>{{ task.status }}</td>
<td>{{ task.get_status_display }}</td>
<td>{{ task.milestone.name }}</td>
<td>
<button class="btn btn-micro" type="button"><i class="icon-edit"></i></button>
<a href="#edittask{{ task.id }}" class="btn btn-micro" data-toggle="modal"><i class="icon-edit"></i></a>
<button class="btn btn-micro" type="button"><i class="icon-remove"></i></button>
</td>
</tr>
@ -114,8 +114,8 @@
</div>
</div>
<!-- Modal -->
<form method="POST" action="/story/{{ story.id }}/priority">
<div id="editprio" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="editPriolLabel" aria-hidden="true">
<form method="POST" action="/story/{{ story.id }}/priority">
{% csrf_token %}
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
@ -129,8 +129,7 @@
class="prio btn btn-small{{code|priobutton}}{% if story.priority == code %} active{% endif %}">{{ prio }}</button>
{% endfor %}
</div>
<hr>
<label>Comment</label>
<label class="after-buttongroup">Comment</label>
<textarea class="input-block-level" rows="6"
placeholder="Add a comment"></textarea>
<input type="hidden" id="priority" name="priority" value="{{ story.priority }}">
@ -139,11 +138,78 @@
<button class="btn" data-dismiss="modal" aria-hidden="true">Close</button>
<input class="btn btn-primary" type="submit" value="Save changes">
</div>
</form>
</div>
</form>
<!-- Edittask Modals -->
{% for task in story.task_set.all %}
<form method="POST" action="/story/task/{{ task.id }}">
<div id="edittask{{ task.id }}" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="editPriolLabel" aria-hidden="true">
{% csrf_token %}
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h3 id="editPrioLabel">Edit
{{task.project.name}}/{{task.series.name}} task</h3>
</div>
<div class="modal-body">
<label>Title <small>(optional)</small></label>
<input type="text" name="title" value="{{ task.title }}">
<label>Assignee</label>
<div class="input-prepend">
<span class="add-on"><i class="icon-user"></i></span>
<input id="prependedInput" type="text" name="assignee"
value="{{task.assignee.username}}">
</div>
<label>Milestone</label>
<div class="btn-group" data-toggle="buttons-radio">
<button type="button" data-value=""
class="btn btn-small ms{{task.id}}
{% if not task.milestone %}active{% endif %}">
None</button>
{% for milestone in milestones %}
{% if milestone.series == task.series %}}
<button type="button" data-value="{{milestone.id}}"
class="btn btn-small
{% if task.milestone == milestone %}active{% endif %}
{% if milestone.active or task.milestone == milestone %}ms{{task.id}}{%endif%}
{% if not milestone.active %}btn-success
{% if task.milestone != milestone %}disabled{%endif%}
{% endif %}"
{% if task.milestone != milestone and not milestone.active %}disabled="disabled"{%endif%}>
{{ milestone.name }}</button>
{% endif %}
{% endfor %}
</div>
<label class="after-buttongroup">Status</label>
<div class="btn-group" data-toggle="buttons-radio">
{% for code, status in taskstatuses %}
<button type="button" data-value="{{code}}"
class="stat{{ task.id }} btn btn-small btn-{{code|taskcolor}}{% if task.status == code %} active{% endif %}">{{ status }}</button>
{% endfor %}
</div>
<label class="after-buttongroup">Comment</label>
<textarea class="input-block-level" rows="3"
placeholder="Add a comment"></textarea>
<input type="hidden" id="ms{{task.id}}" name="milestone" value="{{ task.milestone.id }}">
<input type="hidden" id="status{{task.id}}" name="status" value="{{ task.status }}">
</div>
<div class="modal-footer">
<button class="btn" data-dismiss="modal" aria-hidden="true">Close</button>
<input class="btn btn-primary" type="submit" value="Save changes">
</div>
</div>
</form>
{% endfor %}
{% endblock %}
{% block moarscript %}
$(".prio").click(function() {
$("#priority").val($(this).data("value"));
});
{% for task in story.task_set.all %}
$(".stat{{task.id}}").click(function() {
$("#status{{task.id}}").val($(this).data("value"));
});
$(".ms{{task.id}}").click(function() {
$("#ms{{task.id}}").val($(this).data("value"));
});
{% endfor %}
{% endblock %}

View File

@ -20,7 +20,7 @@ register = template.Library()
badges = ['', ' badge-info', ' badge-success', ' badge-warning',
' badge-important']
buttons = ['', ' btn-info', ' btn-success', ' btn-warning', ' btn-danger']
taskcolors = { 'T': 'info', 'R': 'warning', 'L': 'success' }
@register.filter(name='priobadge')
def priobadge(value):
if value < 5:
@ -34,3 +34,7 @@ def priobutton(value):
return buttons[value]
else:
return buttons[4]
@register.filter(name='taskcolor')
def taskcolor(value):
return taskcolors.get(value, 'info')

View File

@ -21,4 +21,5 @@ urlpatterns = patterns('stories.views',
(r'^(\d+)$', 'view'),
(r'^(\d+)/comment$', 'comment'),
(r'^(\d+)/priority$', 'set_priority'),
(r'^task/(\d+)$', 'edit_task'),
)

View File

@ -17,8 +17,9 @@ from django.contrib.auth.decorators import login_required
from django.views.decorators.http import require_POST
from django.http import HttpResponseRedirect, HttpResponseForbidden
from django.shortcuts import render
from stories.models import Story, Comment
from django.contrib.auth.models import User
from projects.models import Milestone
from stories.models import Story, Task, Comment
def dashboard(request):
return render(request, "stories.dashboard.html")
@ -26,9 +27,12 @@ def dashboard(request):
def view(request, storyid):
story = Story.objects.get(id=storyid)
milestones = Milestone.objects.all()
return render(request, "stories.view.html", {
'story': story,
'milestones': milestones,
'priorities': Story.STORY_PRIORITIES,
'taskstatuses': Task.TASK_STATUSES,
})
@login_required
@ -51,3 +55,37 @@ def set_priority(request, storyid):
story.priority = request.POST['priority']
story.save()
return HttpResponseRedirect('/story/%s' % storyid)
@login_required
@require_POST
def edit_task(request, taskid):
task = Task.objects.get(id=taskid)
try:
actions = []
if (task.title != request.POST['title']):
actions.append("task title")
task.title = request.POST['title']
milestone = Milestone.objects.get(id=request.POST['milestone'])
if (milestone != task.milestone):
actions.append("milestone -> %s" % milestone.name)
task.milestone = milestone
status = request.POST['status']
if (task.status != status):
task.status = status
actions.append("status -> %s" % task.get_status_display())
assignee = User.objects.get(username=request.POST['assignee'])
if (assignee != task.assignee):
actions.append("assignee -> %s" % assignee.username)
task.assignee = assignee
if actions:
msg = "Updated " + ", ".join(actions)
task.save()
newcomment = Comment(story=task.story,
action=msg,
author=request.user,
comment_type="tasks",
content=request.POST.get('comment', ''))
newcomment.save()
except KeyError as e:
print e
return HttpResponseRedirect('/story/%s' % task.story.id)