From 94f4e9ac5873b3fccc2a186dd91da41d98588344 Mon Sep 17 00:00:00 2001 From: Robert Sparks Date: Wed, 10 Jan 2018 18:26:20 +0000 Subject: [PATCH] Simplify the edit nomcom members forms. Fixes #1756. Commit ready for merge. - Legacy-Id: 14504 --- ietf/nomcom/forms.py | 113 +----------------- ietf/nomcom/test_data.py | 4 +- ietf/nomcom/tests.py | 13 +- ietf/nomcom/urls.py | 3 +- ietf/nomcom/views.py | 32 ++++- ietf/templates/nomcom/edit_members.html | 39 ------ .../nomcom/edit_members_preview.html | 50 -------- ietf/templates/nomcom/new_edit_members.html | 35 ++++++ .../templates/nomcom/nomcom_private_base.html | 2 +- 9 files changed, 76 insertions(+), 215 deletions(-) delete mode 100644 ietf/templates/nomcom/edit_members.html delete mode 100644 ietf/templates/nomcom/edit_members_preview.html create mode 100644 ietf/templates/nomcom/new_edit_members.html diff --git a/ietf/nomcom/forms.py b/ietf/nomcom/forms.py index 496a60659..e27b585ea 100644 --- a/ietf/nomcom/forms.py +++ b/ietf/nomcom/forms.py @@ -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): diff --git a/ietf/nomcom/test_data.py b/ietf/nomcom/test_data.py index d0cad55aa..759fe1e39 100644 --- a/ietf/nomcom/test_data.py +++ b/ietf/nomcom/test_data.py @@ -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) diff --git a/ietf/nomcom/tests.py b/ietf/nomcom/tests.py index 185d992b5..2fbb18848 100644 --- a/ietf/nomcom/tests.py +++ b/ietf/nomcom/tests.py @@ -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): diff --git a/ietf/nomcom/urls.py b/ietf/nomcom/urls.py index 50519ca59..3a9447068 100644 --- a/ietf/nomcom/urls.py +++ b/ietf/nomcom/urls.py @@ -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\d{4})/private/merge-nominee/?$', views.private_merge_nominee), url(r'^(?P\d{4})/private/merge-person/?$', views.private_merge_person), url(r'^(?P\d{4})/private/send-reminder-mail/(?P\w+)/$', views.send_reminder_mail), - url(r'^(?P\d{4})/private/edit-members/$', EditMembersFormPreview(EditMembersForm), name='ietf.nomcom.forms.EditMembersFormPreview'), + url(r'^(?P\d{4})/private/edit-members/$', views.edit_members), url(r'^(?P\d{4})/private/edit-nomcom/$', views.edit_nomcom), url(r'^(?P\d{4})/private/chair/templates/$', views.list_templates), url(r'^(?P\d{4})/private/chair/templates/(?P\d+)/$', views.edit_template), diff --git a/ietf/nomcom/views.py b/ietf/nomcom/views.py index a96d6aeea..e196d006f 100644 --- a/ietf/nomcom/views.py +++ b/ietf/nomcom/views.py @@ -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, + }) + diff --git a/ietf/templates/nomcom/edit_members.html b/ietf/templates/nomcom/edit_members.html deleted file mode 100644 index a68662365..000000000 --- a/ietf/templates/nomcom/edit_members.html +++ /dev/null @@ -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 %} -

- Edit members -

- -
- - Fill in this form with the email addresses of nomcom members to register - them with the datatracker as nomcom members. - -
-
- - 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. - -
- -
- {% csrf_token %} - {% bootstrap_form form %} - - - {% buttons %} - - {% endbuttons %} -
- -{% endblock %} diff --git a/ietf/templates/nomcom/edit_members_preview.html b/ietf/templates/nomcom/edit_members_preview.html deleted file mode 100644 index 49b94f843..000000000 --- a/ietf/templates/nomcom/edit_members_preview.html +++ /dev/null @@ -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 %} -

Preview members

- - {% if state.members_info %} -
- {% for member in state.members_info %} -
{{ member.person.name }}
{{ member.email }}
- {% endfor %} -
- {% endif %} - - {% if state.emails_not_found %} -

Members not found

-
    - {% for email in state.emails_not_found %} -
  • {{ email }}
  • - {% endfor %} -
- {% if state.rolodex_url %}Please go to {{ state.rolodex_url }} to add these people.{% endif %} - {% endif %} - -
- {% csrf_token %} - {% for field in form %}{{ field.as_hidden }}{% endfor %} - - - -
- -

Edit members again

- -
- {% csrf_token %} - {% bootstrap_form form %} - - - {% buttons %} - - {% endbuttons %} -
- -{% endblock %} diff --git a/ietf/templates/nomcom/new_edit_members.html b/ietf/templates/nomcom/new_edit_members.html new file mode 100644 index 000000000..703c1636a --- /dev/null +++ b/ietf/templates/nomcom/new_edit_members.html @@ -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 %} + + +{% endblock %} + +{% block subtitle %} - Edit members{% endblock %} + +{% block nomcom_content %} + {% origin %} +

+ Edit members +

+ +
+ {% csrf_token %} + {% bootstrap_form form %} + {% buttons %} + + Cancel + {% endbuttons %} +
+ +{% endblock %} + +{% block js %} + + +{% endblock %} diff --git a/ietf/templates/nomcom/nomcom_private_base.html b/ietf/templates/nomcom/nomcom_private_base.html index 2f7bdc021..273707374 100644 --- a/ietf/templates/nomcom/nomcom_private_base.html +++ b/ietf/templates/nomcom/nomcom_private_base.html @@ -42,7 +42,7 @@
  • Edit Positions
  • Edit Topics
  • {% if nomcom.group.state_id == 'active' %} -
  • Edit Members
  • +
  • Edit Members
  • {% endif %}
  • Configuration Help