Improve shepherd assignation by email.

Check if multiple persons have the same email.
  If person exist assign him/her directly.
  If person doesn't exists inform by email: person, wg chairs and secretariat.
  Inform the user what's going on in each step.
See 
 - Legacy-Id: 2734
This commit is contained in:
Emilio A. Sánchez López 2010-12-24 13:38:34 +00:00
parent 204a4dd72b
commit 61697ed096
12 changed files with 213 additions and 208 deletions

View file

@ -1,50 +1,40 @@
{% extends "base.html" %}
{% block title %}Edit info on {{ doc }}{% endblock %}
{% block morecss %}
form.edit-info #id_state_change_notice_to {
width: 600px;
}
form.edit-info #id_note {
width: 600px;
height: 150px;
}
form.edit-info .actions {
padding-top: 20px;
}
{% endblock %}
{% block content %}
{% extends "wginfo/wg_base.html" %}
{% load ietf_filters %}
<h1>Edit info on {{ doc }}</h1>
Shepherd: {{ doc.shepherd }}
{% block title %}Chage shepherd for {{ doc }}{% endblock %}
{{ form.non_field_errors }}
<form class="edit-info" action="" method="POST">
<table>
{% for field in form %}
<tr>
<th>{{ field.label_tag }}:</th>
<td>{{ field }}
{% ifequal field.name "telechat_date" %}{{ form.returning_item }} {{ form.returning_item.label_tag }} {{ form.returning_item.errors }}{% endifequal %}
{% ifequal field.name "job_owner" %}
{% if user|in_group:"Area_Director" %}
<label><input type="checkbox" name="job_owner" value="{{ login.id }}" /> Assign to me</label>
{% endif %}
{% endifequal %}
{% if field.help_text %}<div class="help">{{ field.help_text }}</div>{% endif %}
{{ field.errors }}</td>
</tr>
{% endfor %}
<tr>
<td></td>
<td class="actions">
<a href="{{ doc.idinternal.get_absolute_url }}">Back</a>
<input type="submit" value="Save"/>
</td>
</tr>
</table>
{% block wg_content %}
<p>
<a href="{% url manage_shepherds wg.group_acronym.acronym %}">Return to shepherd list</a>
</p>
<h1>Change shepherd for {{ doc }}</h1>
<table style="width: 100%;"><tr style="vertical-align: top;"><td style="width: 50%;">
<form action="" method="POST">
<table class="ietf-table" style="width: 100%;">
<tr><th>Actual shepherd</th></tr>
<tr><td>{% if doc.shepherd %}{{ doc.shepherd }}{% else %}No shephered assigned{% endif %}</td></tr>
</table>
<input type="hidden" name="update_shepherd" value="1" />
<input type="submit" name="remove_shepherd" value="Unassign shepherd" />
<input type="submit" name="setme" value="Set me as shepherd of this document" />
</form>
</td><td style="width: 50%;">
<form action="" method="POST">
<table class="ietf-table" style="width: 100%;">
<tr><th>Change shepherd</th></tr>
{% if form.message %}
<tr><td class="message message-{{ form.message.type }}">
{{ form.message.value }}
</td></tr>
{% endif %}
<tr><td>{{ form.as_p }}</td></tr>
</table>
<input type="submit" name="change_sheperd" value="Change shepherd" />
{% if form.can_cancel %}<a href="">No! I don't want to continue</a>{% endif %}
</form>
</td></tr></table>
{% endblock %}

View file

@ -1 +0,0 @@
Designated person with email {{ email }} should get a user/password.

View file

@ -1,26 +1,39 @@
{% extends "wginfo/wg_base.html" %}
{% block morecss %}
{{ block.super }}
.wg-chair-management ul {
list-style: none;
}
.wg-chair-management input {
border: 1px solid green;
}
{% endblock %}
{% block wg_titledetail %}Delegates{% endblock %}
{% block wg_content %}
<div class="wg-chair-management">
<h2>Add new delegate</h2>
{% if add_form.message %}
<div class="message message-{{ add_form.message.type }}">
{{ add_form.message.value }}
</div>
<h2>Manage delegates</h2>
<p><strong>Please,</strong> rembember that you only can assign a maximum of three delegates.</p>
<table style="width: 100%;">
<tr style="vertical-align: top;"><td>
{% if delegates %}
<form action="" method="POST">
<table class="ietf-table" style="width: 100%">
<tr><th>Remove</th><th style="Width: 100%">Delegate name</th></tr>
{% for delegate in delegates %}
<tr class="{% cycle "oddrow" "evenrow" %}"><td><input type="checkbox" name="delete" value="{{ delegate.pk }}" /></td><td>{{ delegate.person }}</td></tr>
{% endfor %}
</table>
<input type="submit" value="Remove delegate(s)" name="remove" />
</form>
{% else %}
No delegates
{% endif %}
</td>
<td>
<table class="ietf-table" style="width: 100%;">
<tr><th>Add new delegate</th></tr>
{% if add_form.message %}
<tr><td class="message message-{{ add_form.message.type }}">
{{ add_form.message.value }}
</td></tr>
{% endif %}
<tr><td>
{% if can_add %}
<form action="" method="POST">
{{ add_form.as_p }}
@ -30,26 +43,11 @@
</p>
</form>
{% else %}
<p>
You can only assign three delegates. Please remove delegates to add a new one.
</p>
{% endif %}
<h2>Delegates</h2>
{% if delegates %}
<form action="" method="POST">
<table>
<tr><th>Remove</th><th>Delegate name</th></tr>
{% for delegate in delegates %}
<tr><td><input type="checkbox" name="delete" value="{{ delegate.pk }}" /></td><td>{{ delegate.person }}</td></tr>
{% endfor %}
</table>
<input type="submit" value="Remove delegate(s)" name="remove" />
</form>
{% else %}
<p>
No delegates
</p>
{% endif %}
</td></tr>
</table>
</td></tr>
</table>
</div>
{% endblock %}

View file

@ -2,6 +2,13 @@
{% block wg_titledetail %}Manage Workflow{% endblock %}
{% block pagehead %}
{{ block.super }}
<script type="text/javascript" src="/js/lib/jquery-1.4.2.min.js"></script>
<script type="text/javascript" src="/js/yui/yui-20100305.js"></script>
<script type="text/javascript" src="/js/base.js"></script>
{% endblock pagehead %}
{% block wg_content %}
<div class="wg-workflow-management">
<h2>Edit workflow</h2>
@ -111,10 +118,6 @@
</div>
</div>
<script type="text/javascript" src="/js/lib/jquery-1.4.2.min.js"></script>
<script type="text/javascript" src="/js/yui/yui-20100305.js"></script>
<script type="text/javascript" src="/js/base.js"></script>
<script type="text/javascript">
//<![CDATA[
var tabView = new YAHOO.widget.TabView('mytabs');

View file

@ -1,4 +1,4 @@
{{ chair }} as a WG Chair of {{ wg }} wants to add you as a {{ wg }} WG Delegate.
{{ chair }} as a WG Chair of {{ wg }} wants to add you as a {{ wg }} {% if shepherd %}shepherd of document {{ shepherd }}{% else %}WG Delegate{% endif %}.
You don't have an user/password to log into the datatracker so you must contact
the Secretariat at iesg-secretary@ietf.org in order to get your credentials.

View file

@ -1,5 +1,5 @@
{{ chair }} as a WG Chair of {{ wg }} wants to add a person with email
{{ delegate_email }} as a WG Delegate.
{{ delegate_email }} as a {% if shepherd %}shepherd of document {{ shepherd }}{% else %}WG Delegate{% endif %}.
This person don't have an user/password to log into the datatracker so
an email has been seent to {{ delegate_email }} in order to he/she contacs the

View file

@ -1,5 +1,5 @@
{{ chair }} as a WG Chair of {{ wg }} wants to add a person with email
{{ delegate_email }} as a WG Delegate.
{{ delegate_email }} as a {% if shepherd %}shepherd of document {{ shepherd }}{% else %}WG Delegate{% endif %}.
This person don't have an user/password to log into the datatracker so
an email has been seent to {{ delegate_email }} in order to he/she contacs the
@ -8,4 +8,4 @@ Secretariat to request his/her credentials.
When he/she gets her credentials then he/she will send an email to
{{ chair }} at {{ chair.email.1 }}.
{{ chair }} could then assign this person as WG Delegate.
{{ chair }} could then assign this person as {% if shepherd %}shepherd of document {{ shepherd }}{% else %}WG Delegate{% endif %}.

View file

@ -34,37 +34,28 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
{% endcomment %}
{% block wg_titledetail %}Documents{% endblock %}
{% block pagehead %}
{{ block.super }}
<script type="text/javascript" src="/js/lib/jquery-1.4.2.min.js"></script>
<script type="text/javascript" src="/js/yui/yui-20100305.js"></script>
<script type="text/javascript" src="/js/base.js"></script>
{% endblock pagehead %}
{% block wg_content %}
<table class="ietf-table ietf-doctable" style="margin-top:16px;">
<tr>
<th class="title">Documents I shepherd</th>
<th class="date">Date</th>
<th class="status">Status</th>
<th class="ad">Area Director</th>
</tr>
{% for doc in my_documents %}
<tr class="{% cycle oddrow,evenrow %}">
<td class="title">
<a href="{% url doc_managing_shepherd wg.group_acronym.acronym doc %}">{{ doc.title }}</a>
</td>
<td class="date">
{{ doc.status.start_date|date:"Y-m" }}
</td>
<td class="status">
{{ doc.status.status }}
</td>
<td class="ad">{{ doc.ad_name|default:"" }}</td>
</tr>
{% endfor %}
</table>
<h2>Documets by its shepherd</h2>
<div id="mytabs" class="yui-navset">
<ul class="yui-nav">
<li class="selected"><a href="#noshepherd"><em>Without shepherd</em></a></li>
<li><a href="#mydocs"><em>I Shepherd</em></a></li>
<li><a href="#othershepherds"><em>Other shepherds</em></a></li>
</ul>
<table class="ietf-table ietf-doctable" style="margin-top:16px;">
<div class="yui-content">
<div id="noshepherd">
<table class="ietf-table ietf-doctable" style="margin-top:16px; width: 100%;">
<tr>
<th class="title">Documents whithout shepherd</th>
<th class="title">Document</th>
<th class="date">Date</th>
<th class="status">Status</th>
<th class="ad">Area Director</th>
@ -87,21 +78,18 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
{% endfor %}
</table>
</div>
<table class="ietf-table ietf-doctable" style="margin-top:16px;">
<div id="mydocs">
<table class="ietf-table ietf-doctable" style="margin-top:16px; width: 100%;">
<tr>
<th class="title">Documents by other shepherds</th>
<th class="title">Document</th>
<th class="date">Date</th>
<th class="status">Status</th>
<th class="ad">Area Director</th>
</tr>
{% regroup other_shepherds by shepherd as regrouped %}
{% for documents in regrouped %}
<tr class="header"><td colspan="4">{{ documents.grouper }}</td></tr>
{% for doc in documents.list %}
{% for doc in my_documents %}
<tr class="{% cycle oddrow,evenrow %}">
<td class="title">
<a href="{% url doc_managing_shepherd wg.group_acronym.acronym doc %}">{{ doc.title }}</a>
@ -115,8 +103,55 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
<td class="ad">{{ doc.ad_name|default:"" }}</td>
</tr>
{% endfor %}
{% endfor %}
</table>
</div>
<div id="othershepherds">
{% regroup other_shepherds by shepherd as regrouped %}
{% for documents in regrouped %}
<h3 style="margin-bottom: 0px;">{{ documents.grouper }}</h3>
<table class="ietf-table ietf-doctable" style="width: 100%;">
<tr>
<th class="title">Document</th>
<th class="date">Date</th>
<th class="status">Status</th>
<th class="ad">Area Director</th>
</tr>
{% for doc in documents.list %}
<tr class="{% cycle oddrow,evenrow %}">
<td class="title">
<a href="{% url doc_managing_shepherd wg.group_acronym.acronym doc %}">{{ doc.title }}</a>
</td>
<td class="date">
{{ doc.status.start_date|date:"Y-m" }}
</td>
<td class="status">
{{ doc.status.status }}
</td>
<td class="ad">{{ doc.ad_name|default:"" }}</td>
</tr>
{% endfor %}
</table>
{% endfor %}
</div>
<script type="text/javascript">
//<![CDATA[
var tabView = new YAHOO.widget.TabView('mytabs');
var url = location.href.split('#');
if (url[1]) {
url[1] = "#"+url[1];
var tabs = tabView.get('tabs');
for (var i = 0; i < tabs.length; i++) {
if (url[1].indexOf(tabs[i].get('href')) == 0) {
tabView.set('activeIndex', i);
break;
}
}
}
//]]>
</script>
{% endblock wg_content %}

View file

@ -13,3 +13,11 @@
<a href="{% url manage_delegates wg.group_acronym.acronym %}">Manage delegates</a>
{% endifequal %} |
{% endif %}
{% if can_manage_shepherds %}
{% ifequal selected "manage_shepherds" %}
<span class="selected">Manage shepherds</span>
{% else %}
<a href="{% url manage_shepherds wg.group_acronym.acronym %}">Manage shepherds</a>
{% endifequal %} |
{% endif %}

View file

@ -178,6 +178,7 @@ class AddDelegateForm(RelatedWGForm):
form_type = forms.CharField(widget=forms.HiddenInput, initial='single')
def __init__(self, *args, **kwargs):
self.shepherd = kwargs.pop('shepherd', False)
super(AddDelegateForm, self).__init__(*args, **kwargs)
self.next_form = self
@ -197,14 +198,23 @@ class AddDelegateForm(RelatedWGForm):
try:
person = self.get_person(email)
except PersonOrOrgInfo.DoesNotExist:
self.next_form = NotExistDelegateForm(wg=self.wg, user=self.user, email=email)
self.next_form = NotExistDelegateForm(wg=self.wg, user=self.user, email=email, shepherd=self.shepherd)
self.next_form.set_message('doesnotexist', 'There is no user with this email allowed to login to the system')
return
except PersonOrOrgInfo.MultipleObjectsReturned:
self.next_form = MultipleDelegateForm(wg=self.wg, user=self.user, email=email)
self.next_form = MultipleDelegateForm(wg=self.wg, user=self.user, email=email, shepherd=self.shepherd)
self.next_form.set_message('multiple', 'There are multiple users with this email in the system')
return
self.create_delegate(person)
if self.shepherd:
self.assign_shepherd(person)
else:
self.create_delegate(person)
def assign_shepherd(self, person):
self.shepherd.shepherd = person
self.shepherd.save()
self.next_form = AddDelegateForm(wg=self.wg, user=self.user, shepherd=self.shepherd)
self.next_form.set_message('success', 'Shepherd assigned successfully')
def create_delegate(self, person):
(delegate, created) = WGDelegate.objects.get_or_create(wg=self.wg,
@ -234,7 +244,10 @@ class MultipleDelegateForm(AddDelegateForm):
def save(self):
person_id = self.cleaned_data.get('persons')
person = PersonOrOrgInfo.objects.get(pk=person_id)
self.create_delegate(person)
if self.shepherd:
self.assign_shepherd(person)
else:
self.create_delegate(person)
class NotExistDelegateForm(MultipleDelegateForm):
@ -264,11 +277,15 @@ class NotExistDelegateForm(MultipleDelegateForm):
return info + super(NotExistDelegateForm, self).as_p()
def send_email(self, email, template):
subject = 'WG Delegate needs system credentials'
if self.shepherd:
subject = 'WG shepherd needs system credentials'
else:
subject = 'WG Delegate needs system credentials'
persons = PersonOrOrgInfo.objects.filter(emailaddress__address=self.email).distinct()
body = render_to_string(template,
{'chair': get_person_for_user(self.user),
'delegate_email': self.email,
'shepherd': self.shepherd,
'delegate_persons': persons,
'wg': self.wg,
})
@ -299,74 +316,15 @@ class NotExistDelegateForm(MultipleDelegateForm):
self.next_form.set_message('success', 'Email sent successfully')
def add_form_factory(request, wg, user):
if request.method != 'POST':
return AddDelegateForm(wg=wg, user=user)
def add_form_factory(request, wg, user, shepherd=False):
if request.method != 'POST' or request.POST.get('update_shepehrd'):
return AddDelegateForm(wg=wg, user=user, shepherd=shepherd)
if request.POST.get('form_type', None) == 'multiple':
return MultipleDelegateForm(wg=wg, user=user, data=request.POST.copy())
return MultipleDelegateForm(wg=wg, user=user, data=request.POST.copy(), shepherd=shepherd)
elif request.POST.get('form_type', None) == 'notexist':
return NotExistDelegateForm(wg=wg, user=user, data=request.POST.copy())
return NotExistDelegateForm(wg=wg, user=user, data=request.POST.copy(), shepherd=shepherd)
elif request.POST.get('form_type', None) == 'single':
return AddDelegateForm(wg=wg, user=user, data=request.POST.copy())
return AddDelegateForm(wg=wg, user=user, data=request.POST.copy(), shepherd=shepherd)
return AddDelegateForm(wg=wg, user=user)
class ManagingShepherdForm(forms.Form):
email = forms.EmailField(required=False)
is_assign_current = forms.BooleanField(required=False)
def __init__(self, *args, **kwargs):
if 'current_person' in kwargs.keys():
self.current_person = kwargs.pop('current_person')
return super(ManagingShepherdForm, self).__init__(*args, **kwargs)
def clean_email(self):
email = self.cleaned_data.get('email')
if not email:
return None
try:
PersonOrOrgInfo.objects. \
filter(emailaddress__type__in=["INET", "Prim", ],
emailaddress__address=email)[:1].get()
except PersonOrOrgInfo.DoesNotExist:
if self.cleaned_data.get('is_assign_current'):
self._send_email(email)
raise forms.ValidationError("Person with such email does not exist")
return email
def clean(self):
print self.cleaned_data.get('email') and self.cleaned_data.get('is_assign_current')
if self.cleaned_data.get('email') and \
self.cleaned_data.get('is_assign_current'):
raise forms.ValidationError("You should choose to assign to current \
person or input the email. Not both at te same time. ")
return self.cleaned_data
def change_shepherd(self, document, save=True):
email = self.cleaned_data.get('email')
if email:
person = PersonOrOrgInfo.objects. \
filter(emailaddress__type__in=["INET", "Prim", ],
emailaddress__address=email)[:1].get()
else:
person = self.current_person
document.shepherd = person
if save:
document.save()
return document
def _send_email(self, email,
template='wgchairs/edit_management_shepherd_email.txt'):
subject = 'WG Delegate needs system credentials'
body = render_to_string(template,
{'email': email,
})
mail = EmailMessage(subject=subject,
body=body,
to=[email, settings.DEFAULT_FROM_EMAIL, ],
from_email=settings.DEFAULT_FROM_EMAIL)
mail.send()
return AddDelegateForm(wg=wg, user=user, shepherd=shepherd)

View file

@ -1,7 +1,8 @@
from django import template
from ietf.wgchairs.accounts import (can_manage_workflow_in_group,
can_manage_delegates_in_group)
can_manage_delegates_in_group,
can_manage_shepherds_in_group)
register = template.Library()
@ -14,6 +15,7 @@ def wgchairs_admin_options(context, wg):
return {'user': user,
'can_manage_delegates': can_manage_delegates_in_group(user, wg),
'can_manage_workflow': can_manage_workflow_in_group(user, wg),
'can_manage_shepherds': can_manage_shepherds_in_group(user, wg),
'wg': wg,
'selected': context.get('selected', None),
}

View file

@ -5,8 +5,7 @@ from django.http import HttpResponseForbidden
from ietf.idrfc.views_search import SearchForm, search_query
from ietf.wgchairs.forms import (RemoveDelegateForm, add_form_factory,
ManagingShepherdForm, workflow_form_factory,
TransitionFormSet)
workflow_form_factory, TransitionFormSet)
from ietf.wgchairs.accounts import (can_manage_delegates_in_group, get_person_for_user,
can_manage_shepherds_in_group,
can_manage_workflow_in_group)
@ -74,6 +73,7 @@ def manage_workflow(request, acronym):
'default_states': default_states,
'default_tags': default_tags,
'formset': formset,
'selected': 'manage_workflow',
}, RequestContext(request))
@ -81,19 +81,30 @@ def managing_shepherd(request, acronym, name):
"""
View for managing the assigned shepherd of a document.
"""
wg = get_object_or_404(IETFWG, group_acronym__acronym=acronym, group_type=1)
user = request.user
person = get_person_for_user(user)
if not can_manage_shepherds_in_group(user, wg):
return HttpResponseForbidden('You have no permission to access this view')
doc = get_object_or_404(InternetDraft, filename=name)
login = IESGLogin.objects.get(login_name=request.user.username)
form = ManagingShepherdForm()
if request.method == "POST":
form = ManagingShepherdForm(request.POST, current_person=login.person)
if form.is_valid():
form.change_shepherd(doc)
add_form = add_form_factory(request, wg, user, shepherd=doc)
if request.method == 'POST':
if request.POST.get('remove_shepherd'):
doc.shepherd = None
doc.save()
elif request.POST.get('setme'):
doc.shepherd = person
doc.save()
elif add_form.is_valid():
add_form.save()
add_form = add_form.get_next_form()
return render_to_response('wgchairs/edit_management_shepherd.html',
dict(doc=doc,
form=form,
user=request.user,
login=login),
form=add_form,
user=user,
selected='manage_shepherds',
wg=wg,
),
context_instance=RequestContext(request))
@ -118,6 +129,7 @@ def wg_shepherd_documents(request, acronym):
'no_shepherd': documents_no_shepherd,
'my_documents': documents_my,
'other_shepherds': documents_other,
'selected': 'manage_shepherds',
'wg': wg,
}
return render_to_response('wgchairs/wg_shepherd_documents.html', context, RequestContext(request))