Simplify the edit nomcom members forms. Fixes #1756. Commit ready for merge.
- Legacy-Id: 14504
This commit is contained in:
parent
15d23299d8
commit
94f4e9ac58
|
@ -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):
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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,
|
||||
})
|
||||
|
||||
|
|
|
@ -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 %}
|
|
@ -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 %}
|
35
ietf/templates/nomcom/new_edit_members.html
Normal file
35
ietf/templates/nomcom/new_edit_members.html
Normal 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 %}
|
|
@ -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>
|
||||
|
|
Loading…
Reference in a new issue