Enable task edition
This commit is contained in:
parent
76aaaef12d
commit
da321c1046
@ -12,6 +12,9 @@
|
||||
.sidebar-nav {
|
||||
padding: 9px 0;
|
||||
}
|
||||
.after-buttongroup {
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
@media (max-width: 980px) {
|
||||
/* Enable use of floated navbar text */
|
||||
|
@ -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']
|
||||
|
@ -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)
|
||||
|
||||
|
||||
|
@ -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 %}
|
||||
|
@ -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')
|
@ -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'),
|
||||
)
|
||||
|
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user