Simplify the edit nomcom members forms. Fixes #1756. Commit ready for merge.

- Legacy-Id: 14504
This commit is contained in:
Robert Sparks 2018-01-10 18:26:20 +00:00
parent 15d23299d8
commit 94f4e9ac58
9 changed files with 76 additions and 215 deletions

View file

@ -1,17 +1,13 @@
from django.conf import settings
from django import forms
from formtools.preview import FormPreview, AUTO_ID
from django.shortcuts import get_object_or_404, redirect
from django.utils.decorators import method_decorator
from django.shortcuts import render
from django.shortcuts import get_object_or_404
from django.urls import reverse
from django.utils.html import mark_safe
from django.forms.widgets import FileInput
from ietf.dbtemplate.forms import DBTemplateForm
from ietf.group.models import Group, Role
from ietf.ietfauth.utils import role_required
from ietf.name.models import RoleName, FeedbackTypeName, NomineePositionStateName
from ietf.group.models import Group
from ietf.name.models import FeedbackTypeName, NomineePositionStateName
from ietf.nomcom.models import ( NomCom, Nomination, Nominee, NomineePosition,
Position, Feedback, ReminderDates, Topic )
from ietf.nomcom.utils import (NOMINATION_RECEIPT_TEMPLATE, FEEDBACK_RECEIPT_TEMPLATE,
@ -21,7 +17,6 @@ from ietf.nomcom.utils import (NOMINATION_RECEIPT_TEMPLATE, FEEDBACK_RECEIPT_TEM
from ietf.person.models import Email
from ietf.person.fields import (SearchableEmailField, SearchableEmailsField,
SearchablePersonField, SearchablePersonsField )
from ietf.utils.fields import MultiEmailField
from ietf.utils.mail import send_mail
from ietf.mailtrigger.utils import gather_address_lists
@ -94,107 +89,9 @@ class MultiplePositionNomineeField(forms.MultipleChoiceField, PositionNomineeFie
return result
class EditMembersForm(forms.Form):
members = MultiEmailField(label="Members email", required=False, widget=forms.Textarea)
class EditMembersFormPreview(FormPreview):
form_template = 'nomcom/edit_members.html'
preview_template = 'nomcom/edit_members_preview.html'
@method_decorator(role_required("Nomcom Chair", "Nomcom Advisor"))
def __call__(self, request, *args, **kwargs):
year = kwargs['year']
group = get_nomcom_group_or_404(year)
self.state['group'] = group
self.state['rolodex_url'] = ROLODEX_URL
groups = group.nomcom_set.all()
self.nomcom = groups and groups[0] or None
self.group = group
self.year = year
return super(EditMembersFormPreview, self).__call__(request, *args, **kwargs)
def preview_get(self, request):
"Displays the form"
f = self.form(auto_id=self.get_auto_id(), initial=self.get_initial(request))
return render(request, self.form_template,
{
'form': f,
'stage_field': self.unused_name('stage'),
'state': self.state,
'year': self.year,
'nomcom': self.nomcom,
'selected': 'edit_members',
}
)
def get_initial(self, request):
members = self.group.role_set.filter(name__slug='member')
if members:
return { "members": ",\r\n".join(role.email.address for role in members) }
return {}
def process_preview(self, request, form, context):
members_email = form.cleaned_data['members']
members_info = []
emails_not_found = []
for email in members_email:
try:
email_obj = Email.objects.get(address=email)
person = email_obj.person
except Email.DoesNotExist:
person = None
if person:
members_info.append({'email': email,
'email_obj': email_obj,
'person': person})
else:
emails_not_found.append(email)
self.state.update({'members_info': members_info,
'emails_not_found': emails_not_found})
def preview_post(self, request):
"Validates the POST data. If valid, displays the preview page. Else, redisplays form."
f = self.form(request.POST, auto_id=AUTO_ID)
context = {'form': f, 'stage_field': self.unused_name('stage'), 'state': self.state,
'year': self.year}
if f.is_valid():
self.process_preview(request, f, context)
context['hash_field'] = self.unused_name('hash')
context['hash_value'] = self.security_hash(request, f)
return render(request, self.preview_template, context )
else:
return render(request, self.form_template, context )
def post_post(self, request):
"Validates the POST data. If valid, calls done(). Else, redisplays form."
f = self.form(request.POST, auto_id=AUTO_ID)
context = {'form': f, 'stage_field': self.unused_name('stage'), 'state': self.state,
'year': self.year}
if f.is_valid():
if self.security_hash(request, f) != request.POST.get(self.unused_name('hash')):
return self.failed_hash(request) # Security hash failed.
self.process_preview(request, f, context)
return self.done(request, f.cleaned_data)
else:
return render(request, self.form_template, context )
def done(self, request, cleaned_data):
members_info = self.state['members_info']
members_email = [member['email'] for member in self.state['members_info']]
members_excluded = self.group.role_set.filter(name__slug='member').exclude(email__address__in=members_email)
members_excluded.delete()
for member in members_info:
Role.objects.get_or_create(name=RoleName.objects.get(slug="member"),
group=self.group,
person=member['person'],
email=member['email_obj'])
return redirect('ietf.nomcom.forms.EditMembersFormPreview', year=self.year)
class NewEditMembersForm(forms.Form):
members = SearchableEmailsField(only_users=True,all_emails=True)
class EditNomcomForm(forms.ModelForm):

View file

@ -114,8 +114,8 @@ def nomcom_test_data():
nomcom.public_key.save('cert', File(open(nomcom_test_cert_file.name, 'r')))
# chair and member
create_person(group, "chair", username=CHAIR_USER)
create_person(group, "member", username=MEMBER_USER)
create_person(group, "chair", username=CHAIR_USER, email_address='%s%s'%(CHAIR_USER,EMAIL_DOMAIN))
create_person(group, "member", username=MEMBER_USER, email_address='%s%s'%(MEMBER_USER,EMAIL_DOMAIN))
# nominee
u, created = User.objects.get_or_create(username=COMMUNITY_USER)

View file

@ -27,7 +27,6 @@ from ietf.nomcom.test_data import nomcom_test_data, generate_cert, check_comment
from ietf.nomcom.models import NomineePosition, Position, Nominee, \
NomineePositionStateName, Feedback, FeedbackTypeName, \
Nomination, FeedbackLastSeen, TopicFeedbackLastSeen
from ietf.nomcom.forms import EditMembersForm, EditMembersFormPreview
from ietf.nomcom.utils import get_nomcom_by_year, make_nomineeposition, get_hash_nominee_position
from ietf.nomcom.management.commands.send_reminders import Command, is_time_to_send
@ -75,7 +74,7 @@ class NomcomViewsTest(TestCase):
self.private_index_url = reverse('ietf.nomcom.views.private_index', kwargs={'year': self.year})
self.private_merge_person_url = reverse('ietf.nomcom.views.private_merge_person', kwargs={'year': self.year})
self.private_merge_nominee_url = reverse('ietf.nomcom.views.private_merge_nominee', kwargs={'year': self.year})
self.edit_members_url = reverse('ietf.nomcom.forms.EditMembersFormPreview', kwargs={'year': self.year})
self.edit_members_url = reverse('ietf.nomcom.views.edit_members', kwargs={'year': self.year})
self.edit_nomcom_url = reverse('ietf.nomcom.views.edit_nomcom', kwargs={'year': self.year})
self.private_nominate_url = reverse('ietf.nomcom.views.private_nominate', kwargs={'year': self.year})
self.private_nominate_newperson_url = reverse('ietf.nomcom.views.private_nominate_newperson', kwargs={'year': self.year})
@ -380,15 +379,7 @@ class NomcomViewsTest(TestCase):
def change_members(self, members):
members_emails = u','.join(['%s%s' % (member, EMAIL_DOMAIN) for member in members])
test_data = {'members': members_emails,
'stage': 1}
# preview
self.client.post(self.edit_members_url, test_data)
hash = EditMembersFormPreview(EditMembersForm).security_hash(None, EditMembersForm(test_data))
test_data.update({'hash': hash, 'stage': 2})
# submit
test_data = {'members': members_emails,}
self.client.post(self.edit_members_url, test_data)
def test_edit_members_view(self):

View file

@ -1,5 +1,4 @@
from ietf.nomcom.forms import EditMembersForm, EditMembersFormPreview
from ietf.nomcom import views
from ietf.message import views as message_views
from ietf.utils.urls import url
@ -24,7 +23,7 @@ urlpatterns = [
url(r'^(?P<year>\d{4})/private/merge-nominee/?$', views.private_merge_nominee),
url(r'^(?P<year>\d{4})/private/merge-person/?$', views.private_merge_person),
url(r'^(?P<year>\d{4})/private/send-reminder-mail/(?P<type>\w+)/$', views.send_reminder_mail),
url(r'^(?P<year>\d{4})/private/edit-members/$', EditMembersFormPreview(EditMembersForm), name='ietf.nomcom.forms.EditMembersFormPreview'),
url(r'^(?P<year>\d{4})/private/edit-members/$', views.edit_members),
url(r'^(?P<year>\d{4})/private/edit-nomcom/$', views.edit_nomcom),
url(r'^(?P<year>\d{4})/private/chair/templates/$', views.list_templates),
url(r'^(?P<year>\d{4})/private/chair/templates/(?P<template_id>\d+)/$', views.edit_template),

View file

@ -16,7 +16,7 @@ from django.forms.models import modelformset_factory, inlineformset_factory
from ietf.dbtemplate.models import DBTemplate
from ietf.dbtemplate.views import template_edit, template_show
from ietf.name.models import NomineePositionStateName, FeedbackTypeName
from ietf.group.models import Group, GroupEvent
from ietf.group.models import Group, GroupEvent
from ietf.message.models import Message
from ietf.nomcom.decorators import nomcom_private_key_required
@ -24,7 +24,8 @@ from ietf.nomcom.forms import (NominateForm, NominateNewPersonForm, FeedbackForm
MergeNomineeForm, MergePersonForm, NomComTemplateForm, PositionForm,
PrivateKeyForm, EditNomcomForm, EditNomineeForm,
PendingFeedbackForm, ReminderDatesForm, FullFeedbackFormSet,
FeedbackEmailForm, NominationResponseCommentForm, TopicForm)
FeedbackEmailForm, NominationResponseCommentForm, TopicForm,
NewEditMembersForm,)
from ietf.nomcom.models import (Position, NomineePosition, Nominee, Feedback, NomCom, ReminderDates,
FeedbackLastSeen, Topic, TopicFeedbackLastSeen, )
from ietf.nomcom.utils import (get_nomcom_by_year, store_nomcom_private_key,
@ -1174,3 +1175,30 @@ def edit_topic(request, year, topic_id=None):
@role_required("Nomcom Chair", "Nomcom Advisor")
def configuration_help(request, year):
return render(request,'nomcom/chair_help.html',{'year':year})
@role_required("Nomcom Chair", "Nomcom Advisor")
def edit_members(request, year):
nomcom = get_nomcom_by_year(year)
if nomcom.group.state_id=='conclude':
return HttpResponseForbidden('This nomcom is closed.')
old_members_email = [r.email for r in nomcom.group.role_set.filter(name='member')]
if request.method=='POST':
form = NewEditMembersForm(data=request.POST)
if form.is_valid():
new_members_email = form.cleaned_data['members']
nomcom.group.role_set.filter( email__in=set(old_members_email)-set(new_members_email) ).delete()
for email in set(new_members_email)-set(old_members_email):
nomcom.group.role_set.create(email=email,person=email.person,name_id='member')
return HttpResponseRedirect(reverse('ietf.nomcom.views.private_index',kwargs={'year':year}))
else:
form = NewEditMembersForm(initial={ 'members' : old_members_email })
return render(request, 'nomcom/new_edit_members.html',
{'nomcom' : nomcom,
'year' : year,
'form': form,
})

View file

@ -1,39 +0,0 @@
{% extends "nomcom/nomcom_private_base.html" %}
{# Copyright The IETF Trust 2015, All Rights Reserved #}
{% load origin %}
{% load bootstrap3 %}
{% block subtitle %} - Edit members{% endblock %}
{% block nomcom_content %}
{% origin %}
<h2>
Edit members
</h2>
<div class="help-block">
Fill in this form with the email addresses of nomcom members to register
them with the datatracker as nomcom members.
</div>
<div class="help-block">
The email addresses should be the primary email addresses of the members'
datatracker accounts, and they should be entered as a comma-separated
list, with optional white-space.
</div>
<form method="post">
{% csrf_token %}
{% bootstrap_form form %}
<input type="hidden" name="{{ stage_field }}" value="1">
{% buttons %}
<input class="btn btn-primary" type="submit" value="Preview">
{% endbuttons %}
</form>
{% endblock %}

View file

@ -1,50 +0,0 @@
{% extends "nomcom/nomcom_private_base.html" %}
{# Copyright The IETF Trust 2015, All Rights Reserved #}
{% load origin %}
{% load bootstrap3 %}
{% block subtitle %} - Preview members{% endblock %}
{% block nomcom_content %}
{% origin %}
<h2>Preview members</h2>
{% if state.members_info %}
<dl>
{% for member in state.members_info %}
<dt>{{ member.person.name }}</dt><dd>{{ member.email }}</dd>
{% endfor %}
</dl>
{% endif %}
{% if state.emails_not_found %}
<h3>Members not found </h3>
<ul>
{% for email in state.emails_not_found %}
<li>{{ email }}</li>
{% endfor %}
</ul>
{% if state.rolodex_url %}Please go to <a href="{{ state.rolodex_url }}">{{ state.rolodex_url }}</a> to add these people.{% endif %}
{% endif %}
<form method="post">
{% csrf_token %}
{% for field in form %}{{ field.as_hidden }}{% endfor %}
<input type="hidden" name="{{ stage_field }}" value="2">
<input type="hidden" name="{{ hash_field }}" value="{{ hash_value }}">
<input class="btn btn-primary" type="submit" value="Submit">
</form>
<h2>Edit members again</h2>
<form method="post">
{% csrf_token %}
{% bootstrap_form form %}
<input type="hidden" name="{{ stage_field }}" value="1">
{% buttons %}
<input class="btn btn-primary"type="submit" value="Preview">
{% endbuttons %}
</form>
{% endblock %}

View file

@ -0,0 +1,35 @@
{% extends "nomcom/nomcom_private_base.html" %}
{# Copyright The IETF Trust 2015, All Rights Reserved #}
{% load origin %}
{% load bootstrap3 %}
{% load staticfiles %}
{% block pagehead %}
<link rel="stylesheet" href="{% static 'select2/select2.css' %}">
<link rel="stylesheet" href="{% static 'select2-bootstrap-css/select2-bootstrap.min.css' %}">
{% endblock %}
{% block subtitle %} - Edit members{% endblock %}
{% block nomcom_content %}
{% origin %}
<h2>
Edit members
</h2>
<form method="post">
{% csrf_token %}
{% bootstrap_form form %}
{% buttons %}
<button class="btn btn-primary" type="submit">Save</button>
<a class="btn btn-default" href="{% url 'ietf.nomcom.views.private_index' year %}">Cancel</a>
{% endbuttons %}
</form>
{% endblock %}
{% block js %}
<script src="{% static 'select2/select2.min.js' %}"></script>
<script src="{% static 'ietf/js/select2-field.js' %}"></script>
{% endblock %}

View file

@ -42,7 +42,7 @@
<li {% if selected == "edit_positions" %}class="active"{% endif %}><a href="{% url 'ietf.nomcom.views.list_positions' year %}">Edit Positions</a></li>
<li {% if selected == "edit_topics" %}class="active"{% endif %}><a href="{% url 'ietf.nomcom.views.list_topics' year %}">Edit Topics</a></li>
{% if nomcom.group.state_id == 'active' %}
<li {% if selected == "edit_members" %}class="active"{% endif %}><a href="{% url 'ietf.nomcom.forms.EditMembersFormPreview' year %}">Edit Members</a></li>
<li {% if selected == "edit_members" %}class="active"{% endif %}><a href="{% url 'ietf.nomcom.views.edit_members' year %}">Edit Members</a></li>
{% endif %}
<li {% if selected == "help" %}class="active"{% endif %}><a href="{% url 'ietf.nomcom.views.configuration_help' year %}">Configuration Help</a></li>
</ul>