Fixed #11: new model - feauture requests (Request), and corresponding views.

portnov [2008-06-14 12:51:34]
Fixed #11: new model - feauture requests (Request), and corresponding views.
Filename
media/css/main.css
mgmt/models.py
mgmt/rights.py
mgmt/views.py
settings.py
templates/create_request.html
templates/project_body.html
templates/request.html
templates/requests.html
urls.py
diff --git a/media/css/main.css b/media/css/main.css
index ddaedb1..aae2231 100644
--- a/media/css/main.css
+++ b/media/css/main.css
@@ -269,6 +269,27 @@ span.pager {
   background: #ccc;
 }

+.request {
+  border: 1px #888 solid;
+  padding: 1ex;
+}
+
+.request-state-1 {
+  background: #eee;
+}
+
+.request-state-2 {
+  background: #fda;
+}
+
+.request-state-3 {
+  background: #ffc;
+}
+
+.request-state-4 {
+  background: #cfc;
+}
+
 .git-tags {
   border-left: 1px #888 solid;
   float: right;
diff --git a/mgmt/models.py b/mgmt/models.py
index d1b3f3a..9115d7c 100644
--- a/mgmt/models.py
+++ b/mgmt/models.py
@@ -58,6 +58,34 @@ class Bug(Object):
   class Admin:
     pass

+class Request(Object):
+  project = models.ForeignKey(Project)
+  status = models.SmallIntegerField()
+  class Meta:
+    ordering = ("-created",)
+  class Admin:
+    pass
+
+class Task(Object):
+  author = models.ForeignKey(User,related_name='created_tasks')
+  to = models.ForeignKey(User)
+  project = models.ForeignKey(Project)
+  bug = models.ForeignKey(Bug,null=True)
+  request = models.ForeignKey(Request,null=True)
+  status = models.SmallIntegerField()
+  class Meta:
+    ordering = ("-created",)
+  class Admin:
+    pass
+
+class Report(Object):
+  author = models.ForeignKey(User)
+  task = models.ForeignKey(Task)
+  class Meta:
+    ordering = ("-created",)
+  class Admin:
+    pass
+
 class Document(Object):
   project = models.ForeignKey(Project)
   author = models.ForeignKey(User)
diff --git a/mgmt/rights.py b/mgmt/rights.py
index 0cd64e7..63bea5d 100644
--- a/mgmt/rights.py
+++ b/mgmt/rights.py
@@ -18,7 +18,7 @@ def can_change_bug_state(user,bug,new_state):
   return False

 def can(user,action,object=None,target=None):
-  if action in ['comment','send bug']:
+  if action in ['comment','send bug','request']:
     return user.is_authenticated()
   if action == 'edit':
     if object.__class__.__name__ == 'Project':
@@ -32,6 +32,9 @@ def can(user,action,object=None,target=None):
   if object.__class__.__name__ == 'PrivateMsg':
     if action == 'delete':
       return user.id == object.reciever.id
+  if object.__class__.__name__ == 'Request':
+    if action == 'change_state':
+      return user in object.project.admins.iterator()
   if object.__class__.__name__ == 'Bug':
     if action == 'set_priority':
       return user in object.project.admins.iterator() and not object.status.id in [1,4,5]
diff --git a/mgmt/views.py b/mgmt/views.py
index 440c006..31c09d8 100644
--- a/mgmt/views.py
+++ b/mgmt/views.py
@@ -44,16 +44,16 @@ def get_comments(request,id,type):
 ############

 class CommentForm(forms.Form):
-  title = forms.CharField(required=False)
-  text = forms.CharField(widget=forms.Textarea())
+  title = forms.CharField(required=False,label=u'Тема')
+  text = forms.CharField(widget=forms.Textarea(),label=u'Текст')

 class BugForm(forms.Form):
-  name = forms.CharField()
-  component = forms.CharField(required=False)
-  your_actions = forms.CharField(widget=forms.Textarea())
-  expected = forms.CharField(widget=forms.Textarea())
-  unexpected = forms.CharField(widget=forms.Textarea())
-  text = forms.CharField(widget=forms.Textarea())
+  name = forms.CharField(label=u'Название')
+  component = forms.CharField(required=False,label=u'Компонент')
+  your_actions = forms.CharField(widget=forms.Textarea(),label=u'Ваши действия')
+  expected = forms.CharField(widget=forms.Textarea(),label=u'Что ожидали получить')
+  unexpected = forms.CharField(widget=forms.Textarea(),label=u'Что получили')
+  text = forms.CharField(widget=forms.Textarea(),label=u'Дополнения')

 class BugPriorityForm(forms.Form):
   priority = forms.ChoiceField(settings.PRIORITY_CHOICES,required=False)
@@ -61,6 +61,13 @@ class BugPriorityForm(forms.Form):
 class BugComplexityForm(forms.Form):
   complexity = forms.ChoiceField(settings.COMPLEXITY_CHOICES,required=False)

+class RequestForm(forms.Form):
+  title = forms.CharField(label=u'Название')
+  text  = forms.CharField(widget=forms.Textarea(),label=u'Текст')
+
+class RequestStateForm(forms.Form):
+  state = forms.ChoiceField(settings.REQUEST_STATES)
+
 class DocForm(forms.Form):
   name = forms.CharField()
   text = forms.CharField(widget=forms.Textarea())
@@ -405,6 +412,57 @@ def delete_private_message(request,msg):
     msg.delete()
     return HttpResponseRedirect(reverse('mgmt.views.user_page',args=(request.user.username,)))

+def requests(request,pid):
+  project = Project.objects.get(pk=pid)
+  rs = project.request_set.all()
+  can_request = can(request.user,'request',project)
+  return render_it('requests.html',
+    {'project': project,
+     'can_request': can_request,
+     'requests': rs},
+    request)
+
+def create_request(request,pid):
+  project = Project.objects.get(pk=pid)
+  if request.method == 'POST':
+    form = RequestForm(request.POST)
+    if form.is_valid():
+      title = form.cleaned_data['title']
+      text  = form.cleaned_data['text']
+      rq = Request(name=title,
+          created = datetime.now(),
+          text=text,
+          status=0,
+          project=project)
+      rq.save()
+      return HttpResponseRedirect(reverse('mgmt.views.requests',args=(pid,)))
+    else:
+      return render_it('create_request.html',
+          {'project': project,
+           'form': form},
+          request)
+  form = RequestForm()
+  return render_it('create_request.html',
+      {'project': project,
+       'form': form},
+      request)
+
+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()
+  can_change_state = can(request.user,'change_state',rq)
+  if can_change_state:
+    state_form = RequestStateForm({'state': rq.status})
+  else:
+    state_form = None
+  return render_it('request.html',
+      {'request': rq,
+       'state_form': state_form},
+      request)
+
 def message_preview(request):
   if request.method=='POST':
     text = request.POST['data']
diff --git a/settings.py b/settings.py
index b079056..3f3a553 100644
--- a/settings.py
+++ b/settings.py
@@ -136,3 +136,9 @@ COMPLEXITY_CHOICES = [(0,u'Тривиально'),
                       (4,u'Сложно'),
                       (5,u'Очень сложно'),
                       (6,u'Потребует изменения архитектуры')]
+
+REQUEST_STATES = [(0,u'Не рассмотрен'),
+                  (1,u'Не принят'),
+                  (2,u'Принят'),
+                  (3,u'В работе'),
+                  (4,u'Реализован')]
diff --git a/templates/create_request.html b/templates/create_request.html
new file mode 100644
index 0000000..814d28a
--- /dev/null
+++ b/templates/create_request.html
@@ -0,0 +1,11 @@
+{% extends "base.html" %}
+{% load prj_filters %}
+
+{% block title %}Создать запрос функциональности для проекта {{project.name}}{% endblock %}
+
+{% block main %}
+<h2>Создать запрос функциональности для проекта {{project.name}}</h2>
+
+{% form form %}
+
+{% endblock %}
diff --git a/templates/project_body.html b/templates/project_body.html
index 4b11587..c44b34b 100644
--- a/templates/project_body.html
+++ b/templates/project_body.html
@@ -11,5 +11,6 @@
       <p class='links'>
         <a href='{% url mgmt.views.project_documents project.id %}'>Документация</a>
         <a href='{% url mgmt.views.project_bugs project.id %}'>Баги</a>
+        <a href='{% url mgmt.views.requests project.id %}'>Запросы функциональности</a>
       </p>
     </div>
diff --git a/templates/request.html b/templates/request.html
new file mode 100644
index 0000000..832a231
--- /dev/null
+++ b/templates/request.html
@@ -0,0 +1,17 @@
+{% extends "base.html" %}
+{% load prj_filters %}
+
+{% block title %}Запрос функциональности: {{request.name}}{% endblock %}
+
+{% block main %}
+<h2>Запрос функциональности: {{request.name}}</h2>
+
+<div class='request request-state-{{request.status}}'>
+  {{request.text|markdown|safe}}
+</div>
+
+{% if state_form %}
+  {% form state_form %}
+{% endif %}
+
+{% endblock %}
diff --git a/templates/requests.html b/templates/requests.html
new file mode 100644
index 0000000..3784a8f
--- /dev/null
+++ b/templates/requests.html
@@ -0,0 +1,28 @@
+{% extends "base.html" %}
+{% load prj_filters %}
+
+{% block title %}Запросы функциональности для проекта {{project.name}}{% endblock %}
+
+{% block main %}
+<h2>Запросы функциональности для проекта {{project.name}}</h2>
+
+{% if requests %}
+  {% if can_request %}
+  <p><a href='{% url mgmt.views.create_request project.id %}'>Создать запрос</a></p>
+  {% endif %}
+  {% for request in requests %}
+  <div class='request request-state-{{request.status}}'>
+    <h3><a href='{% url mgmt.views.one_request request.id %}'>{{request.name}}</a></h3>
+    {{request.text|markdown|safe}}
+  </div>
+  {% endfor %}
+{% else %}
+  <p>Запросов для этого проекта нет.</p>
+{% endif %}
+
+{% if can_request %}
+  <p><a href='{% url mgmt.views.create_request project.id %}'>Создать запрос</a></p>
+{% endif %}
+
+{% endblock %}
+
diff --git a/urls.py b/urls.py
index e72767d..ed777f5 100644
--- a/urls.py
+++ b/urls.py
@@ -6,14 +6,17 @@ urlpatterns = patterns('',
     (r'^projects/(\d+)/$', "mgmt.views.one_project"),
     (r'^projects/(\d+)/bugs/$', "mgmt.views.project_bugs"),
     (r'^projects/(\d+)/docs/$', "mgmt.views.project_documents"),
+    (r'^projects/(\d+)/requests/$', 'mgmt.views.requests'),
     (r'^docs/(\d+)/$', "mgmt.views.one_document"),
     (r'^docs/(\d+)/edit/$', "mgmt.views.edit_document"),
+    (r'^docs/create/(\d+)/$', "mgmt.views.create_document"),
     (r'^bugs/state/(\d+)/$', 'mgmt.views.bugs_by_state'),
     (r'^bugs/(\d+)/$', "mgmt.views.one_bug"),
     (r'^bugs/(\d+)/edit/$', "mgmt.views.edit_bug"),
     (r'^bugs/report/(\d+)/$', 'mgmt.views.bug_report'),
     (r'^bugs/$', "mgmt.views.all_bugs"),
-    (r'^create/doc/(\d+)/$', "mgmt.views.create_document"),
+    (r'^requests/(\d+)/$', 'mgmt.views.one_request'),
+    (r'^requests/create/(\d+)/$', 'mgmt.views.create_request'),
     (r'^users/(\w+)/$', 'mgmt.views.user_page'),
     (r'^message/(\d+)/$', 'mgmt.views.private_message'),
     (r'^message/(\d+)/delete/$', 'mgmt.views.delete_private_message'),
ViewGit