Reports for tasks. Comments for feature-requests.

portnov [2008-06-15 12:56:12]
Reports for tasks. Comments for feature-requests.
Filename
media/css/main.css
mgmt/forms.py
mgmt/rights.py
mgmt/views.py
templates/bug_body.html
templates/create_report.html
templates/edit_report.html
templates/report.html
templates/request.html
templates/task.html
templates/user_page.html
urls.py
diff --git a/media/css/main.css b/media/css/main.css
index 8b1d639..be359a7 100644
--- a/media/css/main.css
+++ b/media/css/main.css
@@ -323,6 +323,20 @@ span.pager {
   background: #dfd;
 }

+.report {
+  border: 1px #ddd solid;
+  padding: 1ex;
+  margin-bottom: 1em;
+}
+
+.related-tasks {
+  border: 1px #888 solid;
+  text-align: right;
+  float: right;
+  background: white;
+  padding: 0.5ex;
+}
+
 .git-tags {
   border-left: 1px #888 solid;
   float: right;
diff --git a/mgmt/forms.py b/mgmt/forms.py
index ba7c1f3..231d27b 100644
--- a/mgmt/forms.py
+++ b/mgmt/forms.py
@@ -3,7 +3,7 @@ import django.newforms as forms
 from django.contrib.auth.models import User
 from django.conf import settings

-from models import Bug,Request,Project,Task
+from models import Bug,Request,Project,Task,Report

 ############
 # Forms
@@ -52,3 +52,8 @@ class TaskModelForm(forms.ModelForm):
 class TaskStateForm(forms.Form):
   state = forms.ChoiceField(settings.TASK_STATES)

+class ReportModelForm(forms.ModelForm):
+  class Meta:
+    model = Report
+    exclude = ("created","author","task")
+
diff --git a/mgmt/rights.py b/mgmt/rights.py
index 3161be8..723634a 100644
--- a/mgmt/rights.py
+++ b/mgmt/rights.py
@@ -32,6 +32,8 @@ def can(user,action,object=None,target=None):
       return user in object.project.team.iterator()
     if cls == 'Task':
       return user.id == object.author.id or user.is_staff
+    if cls == 'Report':
+      return user.id == object.author.id
   if action == 'document':
     return user in object.team.iterator()
   if action == 'create task':
diff --git a/mgmt/views.py b/mgmt/views.py
index 27da8ed..e7dd130 100644
--- a/mgmt/views.py
+++ b/mgmt/views.py
@@ -221,6 +221,7 @@ def one_bug(request,id):
     edit_link = None
   for comment in comments:
     comment.can_delete = can(request.user,'delete',comment)
+  tasks = bug.task_set.all()
   priority = dict(settings.PRIORITY_CHOICES).get(bug.priority,u'Unset')
   complexity = dict(settings.COMPLEXITY_CHOICES).get(bug.complexity,'Unknown')
   return render_it('bug.html',
@@ -231,6 +232,7 @@ def one_bug(request,id):
        'current_page': curr,
        'page_numbers': pages,
        'comments': comments,
+       'tasks': tasks,
        'priority': priority,
        'complexity': complexity,
        'priority_form': priority_form,
@@ -327,11 +329,12 @@ def user_page(request,name):
     messages = None
     form = MessageForm()

-  pr_admin = Project.objects.filter(admins=user)
-  pr_team  = Project.objects.filter(team=user)
+  pr_admin = user.admin_projects.all()
+  pr_team  = user.in_projects.all()
   bugs_resp = Bug.objects.filter(responsible=user,status__id__lt=4)

   tasks = user.task_set.select_related().filter(status__lt=2)
+  reports = user.report_set.select_related().all()

   return render_it('user_page.html',
       {'user_view': user,
@@ -340,12 +343,69 @@ def user_page(request,name):
        'projects_admin': pr_admin,
        'projects_team': pr_team,
        'tasks': tasks,
+       'reports': reports,
        'bugs_resp': bugs_resp},
        request)

 def my_page(request):
   return user_page(request,request.user.username)

+def one_report(request,rid):
+  report = Report.objects.select_related().get(pk=rid)
+  can_edit = can(request.user,'edit',report)
+  return render_it('report.html',
+      {'report': report,
+       'can_edit': can_edit},
+      request)
+
+def task_reports(request,tid):
+  task = Task.objects.get(pk=tid)
+  reports = task.report_set.select_related().all()
+  return render_it('task_reports.html',
+      {'task': task,
+       'reports': reports},
+      request)
+
+@login_required
+def create_report(request,tid):
+  if request.method=='POST':
+    form = ReportModelForm(request.POST)
+    if form.is_valid():
+      report = form.save(commit=False)
+      report.created = datetime.now()
+      report.author = request.user
+      report.task = Task.objects.get(pk=tid)
+      report.save()
+      return HttpResponseRedirect(reverse('mgmt.views.one_task',args=(tid,)))
+    else:
+      return render_it('create_report.html',
+          {'form': form},
+          request)
+  else:
+    form = ReportModelForm()
+    return render_it('create_report.html',
+        {'form': form},
+        request)
+
+@check_auth(Report,'edit')
+def edit_report(request,report):
+  if request.method=='POST':
+    form = ReportModelForm(request.POST,instance=report)
+    if form.is_valid():
+      form.save()
+      return HttpResponseRedirect(reverse('mgmt.views.one_report',args=(report.id,)))
+    else:
+      return render_it('edit_report.html',
+          {'form': form,
+           'report': report},
+          request)
+  else:
+    form = ReportModelForm(instance=report)
+    return render_it('edit_report.html',
+        {'form': form,
+         'report': report},
+        request)
+
 def project_tasks(request,pid):
   project = Project.objects.get(pk=pid)
   tasks = project.task_set.all()
@@ -362,12 +422,16 @@ def one_task(request,tid):
     task.status = request.POST['state']
     task.save()
   can_edit = can(request.user,'edit',task)
+  can_report = request.user.id == task.to.id
+  reports = task.report_set.all()
   if can(request.user,'change_state',task):
     state_form = TaskStateForm({'state': task.status})
   else:
     state_form = None
   return render_it('task.html',
       {'task': task,
+       'can_report': can_report,
+       'reports': reports,
        'state_form': state_form,
        'can_edit': can_edit},
       request)
@@ -507,19 +571,43 @@ def edit_request(request,rq):
 def one_request(request,rid):
   rq = Request.objects.get(pk=rid)
   if request.method=='POST':
-    new_state = request.POST['state']
-    rq.status = new_state
-    rq.save()
+    if request.POST['action']=='change_state':
+      new_state = request.POST['state']
+      rq.status = new_state
+      rq.save()
+    else:
+      title = request.POST['title']
+      text  = request.POST['text']
+      if not title:
+        title = text[:20]+'...'
+      c = Comment(created=datetime.now(),
+          author = request.user,
+          object_id = rid,
+          object_type = 'Request',
+          title = title,
+          text = text)
+      c.save()
   can_change_state = can(request.user,'change_state',rq)
   if can_change_state:
     state_form = RequestStateForm({'state': rq.status})
   else:
     state_form = None
   can_edit = can(request.user,'edit',rq)
+  tasks = rq.task_set.all()
+  page,pages,comments = get_comments(request,rid,'Request')
+  if can(request.user,'comment'):
+    form = CommentForm()
+  else:
+    form = None
   return render_it('request.html',
       {'request': rq,
+       'tasks': tasks,
        'can_edit': can_edit,
-       'state_form': state_form},
+       'state_form': state_form,
+       'current_page': page,
+       'page_numbers': pages,
+       'comments': comments,
+       'form': form},
       request)

 def message_preview(request):
diff --git a/templates/bug_body.html b/templates/bug_body.html
index 24ae9ab..290e95c 100644
--- a/templates/bug_body.html
+++ b/templates/bug_body.html
@@ -18,4 +18,13 @@
         <p><strong>Что ожидали:</strong> {{bug.expected|markdown|safe}}</p>
         <p><strong>Что получили:</strong> {{bug.unexpected|markdown|safe}}</p>
         <div>{{bug.text|markdown|safe}}</div>
+        {% if tasks %}
+        <div class='related-tasks'>
+          Связанные задания:
+          {% for task in tasks %}
+            <a href='{% url mgmt.views.one_task task.id %}'>{{task.name}}</a>
+          {% endfor %}
+        </div>
+        {% endif %}
+
       </div>
diff --git a/templates/create_report.html b/templates/create_report.html
new file mode 100644
index 0000000..4565fd7
--- /dev/null
+++ b/templates/create_report.html
@@ -0,0 +1,10 @@
+{% extends "base.html" %}
+{% load prj_filters %}
+
+{% block title %}Создать отчет{% endblock %}
+
+{% block main %}
+<h2>Создать отчет</h2>
+
+{% form form %}
+{% endblock %}
diff --git a/templates/edit_report.html b/templates/edit_report.html
new file mode 100644
index 0000000..8dcf1ea
--- /dev/null
+++ b/templates/edit_report.html
@@ -0,0 +1,13 @@
+{% extends "base.html" %}
+{% load prj_filters %}
+
+{% block title %}Редактировать отчет{% endblock %}
+
+{% block main %}
+<div class='links'>
+  <a href='{% url mgmt.views.one_report report.id %}'>Просмотреть</a>
+</div>
+<h2>Редактировать отчет: {{report.name}}</h2>
+
+{% form form %}
+{% endblock %}
diff --git a/templates/report.html b/templates/report.html
new file mode 100644
index 0000000..a11029c
--- /dev/null
+++ b/templates/report.html
@@ -0,0 +1,20 @@
+{% extends "base.html" %}
+{% load prj_filters %}
+
+{% block title %}Отчет: {{report.name}}{% endblock %}
+
+{% block main %}
+{% if can_edit %}
+<div class='links'>
+  <a href='{% url mgmt.views.edit_report report.id %}'>Изменить</a>
+</div>
+{% endif %}
+<h2>Отчет: {{report.name}}</h2>
+
+<div class='report'>
+  <p><strong>Автор:</strong> <a href='{% url mgmt.views.user_page report.author.username %}'>{{report.author.username}}</a></p>
+  <p><strong>Задание:</strong> <a href='{% url mgmt.views.one_task report.task.id %}'>{{report.task.name}}</a></p>
+
+  {{report.text|markdown|safe}}
+</div>
+{% endblock %}
diff --git a/templates/request.html b/templates/request.html
index 2c2452a..0f1b5cc 100644
--- a/templates/request.html
+++ b/templates/request.html
@@ -14,12 +14,23 @@
 {% endif %}
 <h2>Запрос функциональности #{{request.id}}: {{request.name}}</h2>

+{% if tasks %}
+  <div class='related-tasks'>
+    Связанные задания:
+    {% for task in tasks %}
+      <a href='{% url mgmt.views.one_task task.id %}'>{{task.name}}</a>
+    {% endfor %}
+  </div>
+{% endif %}
+
 <div class='request request-state-{{request.status}}'>
   {{request.text|markdown|safe}}
 </div>

 {% if state_form %}
-  {% form state_form %}
+  {% form state_form "<input type='hidden' name='action' value='change_state'/>"%}
 {% endif %}

+{% include "comments.html" %}
+
 {% endblock %}
diff --git a/templates/task.html b/templates/task.html
index 929e177..5ebe811 100644
--- a/templates/task.html
+++ b/templates/task.html
@@ -12,6 +12,7 @@
 <h2>Задание: {{task.name}}</h2>

 <div class='task task-state-{{task.status}}'>
+  <p><strong>Проект:</strong> <a href='{% url mgmt.views.one_project task.project.id %}'>{{task.project.name}}</a></p>
   <p><strong>Автор:</strong> <a href='{% url mgmt.views.user_page task.author.username %}'>{{task.author.username}}</a></p>
   <p><strong>Кому:</strong> <a href='{% url mgmt.views.user_page task.to.username %}'>{{task.to.username}}</a></p>

@@ -29,5 +30,22 @@
 {% if state_form %}
   {% form state_form %}
 {% endif %}
+
+{% if reports %}
+  {% if can_report %}
+    <p><a href='{% url mgmt.views.create_report task.id %}'>Создать отчет</a></p>
+  {% endif %}
+  <h3>Отчеты:</h3>
+  {% for report in reports %}
+    <div class='report'>
+      <h4><a href='{% url mgmt.views.one_report report.id %}'>{{report.name}}</a></h4>
+      {{report.text|markdown|safe}}
+    </div>
+  {% endfor %}
+{% endif %}
+
+{% if can_report %}
+  <p><a href='{% url mgmt.views.create_report task.id %}'>Создать отчет</a></p>
+{% endif %}

 {% endblock %}
diff --git a/templates/user_page.html b/templates/user_page.html
index fb57045..e2f7590 100644
--- a/templates/user_page.html
+++ b/templates/user_page.html
@@ -45,6 +45,19 @@
   {% include "tasks_table.html" %}
 {% endif %}

+{% if reports %}
+  <h3>Отчеты:</h3>
+  <table>
+  {% for report in reports %}
+  <tr>
+    <td><a href='{% url mgmt.views.one_task report.task.id%}'>{{report.task.name}}</a></td>
+    <td><a href='{% url mgmt.views.one_report report.id %}'>{{report.name}}</a></td>
+    <td><a href='{% url mgmt.views.edit_report report.id %}'>Изменить</a></td>
+  </tr>
+  {% endfor %}
+  </table>
+{% endif %}
+
 {% if bugs_resp %}
   <h3>Отвечает за баги:</h3>
   <div class='bugs'>
diff --git a/urls.py b/urls.py
index 99bdf3c..d03edc0 100644
--- a/urls.py
+++ b/urls.py
@@ -23,6 +23,9 @@ urlpatterns = patterns('',
     (r'^tasks/(\d+)/$', 'mgmt.views.one_task'),
     (r'^tasks/(\d+)/edit/$', 'mgmt.views.edit_task'),
     (r'^tasks/create/(\d+)/$', 'mgmt.views.create_task'),
+    (r'^reports/(\d+)/$', 'mgmt.views.one_report'),
+    (r'^reports/(\d+)/edit/$', 'mgmt.views.edit_report'),
+    (r'^reports/create/(\d+)/$', 'mgmt.views.create_report'),
     (r'^message/(\d+)/$', 'mgmt.views.private_message'),
     (r'^message/(\d+)/delete/$', 'mgmt.views.delete_private_message'),
     (r'^preview/$', 'mgmt.views.message_preview'),
ViewGit