diff --git a/ietf/templates/wgchairs/confirm_management_writeup.html b/ietf/templates/wgchairs/confirm_management_writeup.html
new file mode 100644
index 000000000..ae23f4a97
--- /dev/null
+++ b/ietf/templates/wgchairs/confirm_management_writeup.html
@@ -0,0 +1,55 @@
+{% extends "wginfo/wg_base.html" %}
+{% load ietf_filters wgchairs_tags %}
+
+{% block title %}Chage shepherd for {{ doc }}{% endblock %}
+
+{% block wg_content %}
+
+
+Return to shepherd list
+
+
+Updatting write-up for {{ doc }}
+
+
+Before you modify the protocol write-up please revise the 'Doc Shepherd Follow-up Underway' annotation tag and set or reset it if appropriate.
+
+
+Remember that you must provide a comment if you change the annotation tag state.
+
+
+
+{% endblock %}
diff --git a/ietf/templates/wgchairs/draft_state.html b/ietf/templates/wgchairs/draft_state.html
new file mode 100644
index 000000000..956ebd44f
--- /dev/null
+++ b/ietf/templates/wgchairs/draft_state.html
@@ -0,0 +1 @@
+{{ state.name }}
diff --git a/ietf/templates/wgchairs/edit_management_writeup.html b/ietf/templates/wgchairs/edit_management_writeup.html
new file mode 100644
index 000000000..3f8cc801b
--- /dev/null
+++ b/ietf/templates/wgchairs/edit_management_writeup.html
@@ -0,0 +1,65 @@
+{% extends "wginfo/wg_base.html" %}
+{% load ietf_filters wgchairs_tags %}
+
+{% block title %}Chage shepherd for {{ doc }}{% endblock %}
+
+{% block wg_content %}
+
+
+Return to shepherd list
+
+
+Change protocol write-up for {{ doc }}
+
+
+Draft state | Actual protocol write-up | Last updated |
+{% show_state doc %} | {{ writeup.writeup|linebreaksbr }} | {% if writeup %}{{ writeup.date }} by {{ writeup.person }}{% endif %} |
+
+
+
+Please, note that the 'Doc Shepherd Follow-up Underway' annotation tag is {% if not followup %}NOT{% endif %} setted for {{ doc }}.
+
+
+{% if can_edit %}
+
+{% else %}
+
+ Edit protocol write-up |
+
+
+ You can not edit or upload the protocol write-up for {{ doc }} cause the draft is not on "WG Consensus: Waiting for Write-Up" state.
+
+
+ Please contact with the {{ wg }} Working Group chair.
+
+ |
+
+{% endif %}
+{% endblock %}
diff --git a/ietf/templates/wgchairs/shepherd_document_row.html b/ietf/templates/wgchairs/shepherd_document_row.html
new file mode 100644
index 000000000..dec1a12dc
--- /dev/null
+++ b/ietf/templates/wgchairs/shepherd_document_row.html
@@ -0,0 +1,17 @@
+{% load wgchairs_tags %}
+
+
+
+ {{ doc.title }}
+ |
+
+ {{ doc.status.status }}
+ |
+
+ {% writeup doc %}
+ [Edit]
+ |
+
+ {% writeupdate doc %}
+ |
+
diff --git a/ietf/templates/wgchairs/wg_shepherd_documents.html b/ietf/templates/wgchairs/wg_shepherd_documents.html
index 468970da2..9cb5fff36 100644
--- a/ietf/templates/wgchairs/wg_shepherd_documents.html
+++ b/ietf/templates/wgchairs/wg_shepherd_documents.html
@@ -56,25 +56,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Document |
- Date |
Status |
- Area Director |
+ Protocol write-up |
+ Protocol write-up last update |
{% for doc in no_shepherd %}
-
-
- {{ doc.title }}
- |
-
- {{ doc.status.start_date|date:"Y-m" }}
- |
-
- {{ doc.status.status }}
- |
- {{ doc.ad_name|default:"" }} |
-
-
+ {% include "wgchairs/shepherd_document_row.html" %}
{% endfor %}
@@ -84,25 +72,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Document |
- Date |
Status |
- Area Director |
+ Protocol write-up |
+ Protocol write-up last update |
{% for doc in my_documents %}
-
-
- {{ doc.title }}
- |
-
- {{ doc.status.start_date|date:"Y-m" }}
- |
-
- {{ doc.status.status }}
- |
- {{ doc.ad_name|default:"" }} |
-
-
+ {% include "wgchairs/shepherd_document_row.html" %}
{% endfor %}
@@ -115,23 +91,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Document |
- Date |
Status |
- Area Director |
+ Protocol write-up |
+ Protocol write-up last update |
{% for doc in documents.list %}
-
-
- {{ doc.title }}
- |
-
- {{ doc.status.start_date|date:"Y-m" }}
- |
-
- {{ doc.status.status }}
- |
- {{ doc.ad_name|default:"" }} |
-
+ {% include "wgchairs/shepherd_document_row.html" %}
{% endfor %}
{% endfor %}
diff --git a/ietf/wgchairs/accounts.py b/ietf/wgchairs/accounts.py
index 2f751c00a..dd8ec110b 100644
--- a/ietf/wgchairs/accounts.py
+++ b/ietf/wgchairs/accounts.py
@@ -1,9 +1,21 @@
+def is_area_director_for_group(person, group):
+ return bool(group.area.area.areadirector_set.filter(person=person).count())
+
+
def is_group_chair(person, group):
if group.chairs().filter(person=person):
return True
return False
+def is_group_delegate(person, group):
+ return bool(group.wgdelegate_set.filter(person=person).count())
+
+
+def is_document_shepherd(person, document):
+ return person == document.shepherd
+
+
def get_person_for_user(user):
try:
return user.get_profile().person()
@@ -51,3 +63,22 @@ def can_manage_shepherd_of_a_document(user, document):
if not person or not document.group:
return False
return can_manage_shepherds_in_group(user, document.group.ietfwg)
+
+
+def can_manage_writeup_of_a_document_no_state(user, document):
+ person = get_person_for_user(user)
+ if not person or not document.group:
+ return False
+ group = document.group.ietfwg
+ return (is_group_chair(person, group) or
+ is_areadirector_for_group(person, group) or
+ is_group_delegate(person, group))
+
+
+def can_manage_writeup_of_a_document(user, document):
+ person = get_person_for_user(user)
+ if not person or not document.group:
+ return False
+ group = document.group.ietfwg
+ return (can_manage_writeup_of_a_document_no_state(user, document) or
+ is_document_shepherd(person, doc))
diff --git a/ietf/wgchairs/forms.py b/ietf/wgchairs/forms.py
index 19b4965c5..fa7dcf3cc 100644
--- a/ietf/wgchairs/forms.py
+++ b/ietf/wgchairs/forms.py
@@ -6,9 +6,10 @@ from django.forms.models import BaseModelFormSet
from django.template.loader import render_to_string
from django.utils.safestring import mark_safe
-from ietf.wgchairs.models import WGDelegate
+from ietf.wgchairs.models import WGDelegate, ProtoWriteUp
from ietf.wgchairs.accounts import get_person_for_user
-from ietf.ietfworkflows.utils import get_default_workflow_for_wg, get_workflow_for_wg
+from ietf.ietfworkflows.utils import (get_default_workflow_for_wg, get_workflow_for_wg,
+ update_tags, FOLLOWUP_TAG)
from ietf.idtracker.models import PersonOrOrgInfo
from workflows.models import Transition
@@ -328,3 +329,48 @@ def add_form_factory(request, wg, user, shepherd=False):
return AddDelegateForm(wg=wg, user=user, data=request.POST.copy(), shepherd=shepherd)
return AddDelegateForm(wg=wg, user=user, shepherd=shepherd)
+
+
+class WriteUpEditForm(RelatedWGForm):
+
+ writeup = forms.CharField(widget=forms.Textarea, required=False)
+ followup = forms.BooleanField(required=False)
+ comment = forms.CharField(widget=forms.Textarea, required=False)
+
+
+ def __init__(self, *args, **kwargs):
+ self.doc = kwargs.pop('doc', None)
+ self.doc_writeup = self.doc.protowriteup_set.all()
+ if self.doc_writeup.count():
+ self.doc_writeup=self.doc_writeup[0]
+ else:
+ self.doc_writeup=None
+ super(WriteUpEditForm, self).__init__(*args, **kwargs)
+
+ def get_writeup(self):
+ return self.data.get('writeup', self.doc_writeup and self.doc_writeup.writeup or '')
+
+ def save(self):
+ if not self.doc_writeup:
+ self.doc_writeup = ProtoWriteUp.objects.create(
+ person=get_person_for_user(self.user),
+ draft=self.doc,
+ writeup=self.cleaned_data['writeup'])
+ else:
+ self.doc_writeup.writeup = self.cleaned_data['writeup']
+ self.doc_writeup.save()
+ if self.data.get('modify_tag', False):
+ followup = self.cleaned_data.get('followup', False)
+ comment = self.cleaned_data.get('comment', False)
+ if followup:
+ update_tags(self.doc, comment, set_tags=[FOLLOWUP_TAG])
+ else:
+ update_tags(self.doc, comment, reset_tags=[FOLLOWUP_TAG])
+ return self.doc_writeup
+
+ def is_valid(self):
+ if self.data.get('confirm', False) and self.data.get('modify_tag', False):
+ self.fields['comment'].required = True
+ else:
+ self.fields['comment'].required = False
+ return super(WriteUpEditForm, self).is_valid()
diff --git a/ietf/wgchairs/templatetags/wgchairs_tags.py b/ietf/wgchairs/templatetags/wgchairs_tags.py
index 8cf9d9783..e81301c78 100644
--- a/ietf/wgchairs/templatetags/wgchairs_tags.py
+++ b/ietf/wgchairs/templatetags/wgchairs_tags.py
@@ -1,5 +1,6 @@
from django import template
+from ietf.ietfworkflows.utils import get_state_for_draft
from ietf.wgchairs.accounts import (can_manage_workflow_in_group,
can_manage_delegates_in_group,
can_manage_shepherds_in_group)
@@ -19,3 +20,27 @@ def wgchairs_admin_options(context, wg):
'wg': wg,
'selected': context.get('selected', None),
}
+
+@register.simple_tag
+def writeup(doc):
+ writeup = doc.protowriteup_set.all()
+ if not writeup.count():
+ return ''
+ else:
+ return writeup[0].writeup
+
+
+@register.simple_tag
+def writeupdate(doc):
+ writeup = doc.protowriteup_set.all()
+ if not writeup.count():
+ return ''
+ else:
+ return writeup[0].date
+
+
+@register.inclusion_tag('wgchairs/draft_state.html', takes_context=True)
+def show_state(context, doc):
+ return {'doc': doc,
+ 'state': get_state_for_draft(doc),
+ }
diff --git a/ietf/wgchairs/urls.py b/ietf/wgchairs/urls.py
index ab69bf8d6..d60c7b61d 100644
--- a/ietf/wgchairs/urls.py
+++ b/ietf/wgchairs/urls.py
@@ -7,4 +7,5 @@ urlpatterns = patterns('ietf.wgchairs.views',
url(r'^delegates/$', 'manage_delegates', name='manage_delegates'),
url(r'^shepherds/$', 'wg_shepherd_documents', name='manage_shepherds'),
url(r'^shepherds/(?P[^/]+)/$', 'managing_shepherd', name='doc_managing_shepherd'),
+ url(r'^shepherds/(?P[^/]+)/writeup/$', 'managing_writeup', name='doc_managing_writeup'),
)
diff --git a/ietf/wgchairs/views.py b/ietf/wgchairs/views.py
index ce353e511..b03c91b29 100644
--- a/ietf/wgchairs/views.py
+++ b/ietf/wgchairs/views.py
@@ -5,13 +5,21 @@ from django.http import HttpResponseForbidden, Http404
from ietf.idrfc.views_search import SearchForm, search_query
from ietf.wgchairs.forms import (RemoveDelegateForm, add_form_factory,
- workflow_form_factory, TransitionFormSet)
+ workflow_form_factory, TransitionFormSet,
+ WriteUpEditForm)
from ietf.wgchairs.accounts import (can_manage_delegates_in_group, get_person_for_user,
can_manage_shepherds_in_group,
can_manage_workflow_in_group,
- can_manage_shepherd_of_a_document)
+ can_manage_shepherd_of_a_document,
+ can_manage_writeup_of_a_document,
+ can_manage_writeup_of_a_document_no_state,
+ )
from ietf.ietfworkflows.utils import (get_workflow_for_wg,
- get_default_workflow_for_wg)
+ get_default_workflow_for_wg,
+ get_state_by_name,
+ get_annotation_tags_for_draft,
+ get_state_for_draft, WAITING_WRITEUP,
+ FOLLOWUP_TAG)
def manage_delegates(request, acronym):
@@ -136,3 +144,65 @@ def wg_shepherd_documents(request, acronym):
'wg': wg,
}
return render_to_response('wgchairs/wg_shepherd_documents.html', context, RequestContext(request))
+
+def managing_writeup(request, acronym, name):
+ wg = get_object_or_404(IETFWG, group_acronym__acronym=acronym, group_type=1)
+ user = request.user
+ person = get_person_for_user(user)
+ doc = get_object_or_404(InternetDraft, filename=name)
+ if not can_manage_writeup_of_a_document(user, doc):
+ raise Http404
+ current_state = get_state_for_draft(doc)
+ can_edit = True
+ if current_state != get_state_by_name(WAITING_WRITEUP) and not can_manage_writeup_of_a_document_no_state(user,doc):
+ can_edit = False
+ writeup = doc.protowriteup_set.all()
+ if writeup.count():
+ writeup = writeup[0]
+ else:
+ writeup = None
+ error = False
+ followup_tag = get_annotation_tags_for_draft(doc).filter(annotation_tag__name=FOLLOWUP_TAG)
+ followup = bool(followup_tag.count())
+ if request.method == 'POST':
+ form = WriteUpEditForm(wg=wg, doc=doc, user=user, data=request.POST, files=request.FILES)
+ if request.FILES.get('uploaded_writeup', None):
+ try:
+ newwriteup = request.FILES['uploaded_writeup'].read().encode('ascii')
+ form.data.update({'writeup': newwriteup})
+ except:
+ form.set_message('error', 'You have try to upload a non ascii file')
+ error = True
+ valid = form.is_valid()
+ if (valid and not error and not request.POST.get('confirm', None)) or (not valid and not error):
+ if not valid:
+ form.set_message('error', 'You have to specify a comment')
+ return render_to_response('wgchairs/confirm_management_writeup.html',
+ dict(doc=doc,
+ user=user,
+ selected='manage_shepherds',
+ wg=wg,
+ followup=followup,
+ form=form,
+ writeup=writeup,
+ can_edit=can_edit,
+ ),
+ context_instance=RequestContext(request))
+ elif valid and not error:
+ writeup = form.save()
+ form = WriteUpEditForm(wg=wg, doc=doc, user=user)
+ followup_tag = get_annotation_tags_for_draft(doc).filter(annotation_tag__name=FOLLOWUP_TAG)
+ followup = bool(followup_tag.count())
+ else:
+ form = WriteUpEditForm(wg=wg, doc=doc, user=user)
+ return render_to_response('wgchairs/edit_management_writeup.html',
+ dict(doc=doc,
+ user=user,
+ selected='manage_shepherds',
+ wg=wg,
+ form=form,
+ writeup=writeup,
+ followup=followup,
+ can_edit=can_edit,
+ ),
+ context_instance=RequestContext(request))