Initial version of forms and views for mailing list submissions.
The nonwg_lists/submit wizard is nearly done; it needs templates and to figure out why submit from step 2 goes back to step 1 instead of calling done. The req_list wizard is just started. It needs to get the incoming value of domain_name as an alternat version of dname, and be able to get dname from GET args to handle the javascript redirect. It also needs all the workflow ("I'm allowed to create this list", who-is-approver, etc.) and additional forms. - Legacy-Id: 122
This commit is contained in:
parent
95209614b5
commit
2739083fbe
ietf
106
ietf/mailinglists/forms.py
Normal file
106
ietf/mailinglists/forms.py
Normal file
|
@ -0,0 +1,106 @@
|
|||
from django import newforms as forms
|
||||
from models import NonWgMailingList, ImportedMailingList
|
||||
from ietf.idtracker.models import PersonOrOrgInfo, GroupIETF
|
||||
|
||||
class NonWgStep1(forms.Form):
|
||||
add_edit = forms.ChoiceField(choices=(
|
||||
('add', 'Add a new entry'),
|
||||
('edit', 'Modify an existing entry'),
|
||||
('delete', 'Delete an existing entry'),
|
||||
), widget=forms.RadioSelect)
|
||||
list_id = forms.ChoiceField(required=False)
|
||||
list_id_delete = forms.ChoiceField(required=False)
|
||||
def add_edit_fields(self):
|
||||
field = self['add_edit']
|
||||
return field.as_widget(field.field.widget)
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(NonWgStep1, self).__init__(*args, **kwargs)
|
||||
choices=[('', '-- Select an item from the list below')] + NonWgMailingList.choices()
|
||||
self.fields['list_id'].choices = choices
|
||||
self.fields['list_id_delete'].choices = choices
|
||||
def clean_list_id(self):
|
||||
if self.clean_data.get('add_edit', None) == 'edit':
|
||||
if not self.clean_data.get('list_id'):
|
||||
raise forms.ValidationError, 'Please pick a mailing list to modify'
|
||||
return self.clean_data['list_id']
|
||||
def clean_list_id_delete(self):
|
||||
if self.clean_data.get('add_edit', None) == 'delete':
|
||||
if not self.clean_data.get('list_id_delete'):
|
||||
raise forms.ValidationError, 'Please pick a mailing list to delete'
|
||||
return self.clean_data['list_id_delete']
|
||||
|
||||
class ListReqStep1(forms.Form):
|
||||
DOMAIN_CHOICES = (
|
||||
('ietf.org', 'ietf.org'),
|
||||
('iab.org', 'iab.org'),
|
||||
('irtf.org', 'irtf.org'),
|
||||
)
|
||||
mail_type = forms.ChoiceField(choices=(
|
||||
('newwg', 'Create new WG email list at ietf.org'),
|
||||
('movewg', 'Move existing WG email list to ietf.org'),
|
||||
('closewg', 'Close existing WG email list at ietf.org'),
|
||||
('newnon', 'Create new non-WG email list at selected domain above'),
|
||||
('movenon', 'Move existing non-WG email list to selected domain above'),
|
||||
('closenon', 'Close existing non-WG email list at selected domain above'),
|
||||
), widget=forms.RadioSelect)
|
||||
group = forms.ChoiceField(required=False)
|
||||
domain_name = forms.ChoiceField(choices=DOMAIN_CHOICES, required=False)
|
||||
list_to_close = forms.ChoiceField(required=False)
|
||||
def mail_type_fields(self):
|
||||
field = self['mail_type']
|
||||
return field.as_widget(field.field.widget)
|
||||
def __init__(self, *args, **kwargs):
|
||||
dname = kwargs.get('dname', 'ietf.org')
|
||||
super(ListReqStep1, self).__init__(*args, **kwargs)
|
||||
self.fields['group'].choices = [('', '-- Select Working Group')] + GroupIETF.choices()
|
||||
self.fields['list_to_close'].choices = [('', '-- Select List To Close')] + ImportedMailingList.choices(dname)
|
||||
self.fields['domain_name'].initial = dname
|
||||
def clean_group(self):
|
||||
if self.clean_data.get('mail_type', '').endswith('wg'):
|
||||
if not self.clean_data.get('group'):
|
||||
raise forms.ValidationError, 'Please pick a working group'
|
||||
return self.clean_data['group']
|
||||
def clean_list_to_close(self):
|
||||
if self.clean_data.get('mail_type', '') == 'closenon':
|
||||
if not self.clean_data.get('list_to_close'):
|
||||
raise forms.ValidationError, 'Please pick a list to close'
|
||||
return self.clean_data['list_to_close']
|
||||
|
||||
# multiwidget for separate scheme and rest for urls
|
||||
# todo: can the clean return the "smart" value?
|
||||
class UrlMultiWidget(forms.MultiWidget):
|
||||
def decompress(self, value):
|
||||
if value:
|
||||
if '//' in value:
|
||||
(scheme, rest) = value.split('//', 1)
|
||||
scheme += '//'
|
||||
else:
|
||||
scheme = 'http://'
|
||||
rest = value
|
||||
return [scheme, rest]
|
||||
else:
|
||||
return ['', '']
|
||||
|
||||
def __init__(self, choices=(('http://', 'http://'), ('https://', 'https://')), attrs=None):
|
||||
widgets = (forms.RadioSelect(choices=choices, attrs=attrs), forms.TextInput(attrs=attrs))
|
||||
super(UrlMultiWidget, self).__init__(widgets, attrs)
|
||||
|
||||
def format_output(self, rendered_widgets):
|
||||
return u'%s\n%s\n<br/>' % ( u'<br/>\n'.join(["%s" % w for w in rendered_widgets[0]]), rendered_widgets[1] )
|
||||
|
||||
|
||||
class PickApprover(forms.Form):
|
||||
"""
|
||||
When instantiating, supply a list of person tags in approvers=
|
||||
"""
|
||||
approver = forms.ChoiceField(choices=(
|
||||
('', '-- Pick an approver from the list below'),
|
||||
))
|
||||
def __init__(self, approvers, *args, **kwargs):
|
||||
super(PickApprover, self).__init__(*args, **kwargs)
|
||||
self.fields['approver'].choices = [('', '-- Pick an approver from the list below')] + [(person.person_or_org_tag, str(person)) for person in PersonOrOrgInfo.objects.filter(pk__in=approvers)]
|
||||
|
||||
class DeletionPickApprover(PickApprover):
|
||||
ds_name = forms.CharField(label = 'Enter your name', widget = forms.TextInput(attrs = {'size': 45}))
|
||||
ds_email = forms.EmailField(label = 'Enter your email', widget = forms.TextInput(attrs = {'size': 45}))
|
||||
msg_to_ad = forms.CharField(label = 'Message to the Area Director', widget = forms.Textarea(attrs = {'rows': 5, 'cols': 50}))
|
|
@ -2,12 +2,18 @@ from django.db import models
|
|||
from ietf.idtracker.models import Acronym, Areas, PersonOrOrgInfo
|
||||
|
||||
class ImportedMailingList(models.Model):
|
||||
group_acronym = models.ForeignKey(Acronym)
|
||||
list_acronym = models.CharField(blank=True, maxlength=255)
|
||||
list_name = models.CharField(blank=True, maxlength=255)
|
||||
list_domain = models.CharField(blank=True, maxlength=25)
|
||||
group_acronym = models.ForeignKey(Acronym, null=True)
|
||||
acronym = models.CharField(maxlength=255, db_column='list_acronym')
|
||||
name = models.CharField(blank=True, maxlength=255, db_column='list_name')
|
||||
domain = models.CharField(blank=True, maxlength=25, db_column='list_domain')
|
||||
def __str__(self):
|
||||
return self.list_name or self.group_acronym
|
||||
return self.name or self.group_acronym
|
||||
def choices(dname):
|
||||
objects = ImportedMailingList.objects.all().filter(domain__icontains=dname).exclude(acronym__iendswith='announce')
|
||||
if dname == "ietf.org":
|
||||
objects = objects.exclude(acronym__istartswith='ietf').exclude(acronym__icontains='iesg')
|
||||
return [(list.acronym, list.acronym) for list in objects]
|
||||
choices = staticmethod(choices)
|
||||
class Meta:
|
||||
db_table = 'imported_mailing_list'
|
||||
class Admin:
|
||||
|
@ -72,22 +78,25 @@ class MailingList(models.Model):
|
|||
class NonWgMailingList(models.Model):
|
||||
id = models.CharField(primary_key=True, maxlength=35)
|
||||
purpose = models.TextField(blank=True)
|
||||
area_acronym = models.ForeignKey(Areas)
|
||||
admin = models.TextField(blank=True)
|
||||
list_url = models.CharField(maxlength=255)
|
||||
s_name = models.CharField(blank=True, maxlength=255)
|
||||
s_email = models.CharField(blank=True, maxlength=255)
|
||||
area = models.ForeignKey(Areas, db_column='area_acronym_id')
|
||||
admin = models.TextField("Administrator(s)' Email Address(es)", blank=True)
|
||||
list_url = models.CharField("List URL", maxlength=255)
|
||||
s_name = models.CharField("Submitter's Name", blank=True, maxlength=255)
|
||||
s_email = models.CharField("Submitter's Email Address", blank=True, maxlength=255)
|
||||
# Can be 0, 1, -1, or what looks like a person_or_org_tag, positive or neg.
|
||||
# The values less than 1 don't get displayed on the list of lists.
|
||||
status = models.IntegerField()
|
||||
list_name = models.CharField(blank=True, maxlength=255)
|
||||
subscribe_url = models.CharField(blank=True, maxlength=255)
|
||||
subscribe_other = models.TextField(blank=True)
|
||||
list_name = models.CharField("Mailing List Name", unique=True, maxlength=255)
|
||||
subscribe_url = models.CharField("Subscribe URL", blank=True, maxlength=255)
|
||||
subscribe_other = models.TextField("Subscribe Other", blank=True)
|
||||
ds_name = models.CharField(blank=True, maxlength=255)
|
||||
ds_email = models.CharField(blank=True, maxlength=255)
|
||||
msg_to_ad = models.TextField(blank=True)
|
||||
def __str__(self):
|
||||
return self.list_name
|
||||
def choices():
|
||||
return [(list.id, list.list_name) for list in NonWgMailingList.objects.all().filter(status__gt=0)]
|
||||
choices = staticmethod(choices)
|
||||
class Meta:
|
||||
db_table = 'none_wg_mailing_list'
|
||||
ordering = ['list_name']
|
||||
|
|
|
@ -1,8 +1,15 @@
|
|||
from django.conf.urls.defaults import *
|
||||
from ietf.idtracker.models import Areas
|
||||
from ietf.mailinglists import views
|
||||
from ietf.mailinglists.models import NonWgMailingList
|
||||
from ietf.mailinglists.forms import NonWgStep1
|
||||
|
||||
urlpatterns = patterns('django.views.generic.list_detail',
|
||||
(r'^area_lists/$', 'object_list', { 'queryset': Areas.objects.filter(status=1).select_related().order_by('acronym.acronym'), 'template_name': 'mailinglists/areas_list.html' }),
|
||||
(r'^nonwg_lists/$', 'object_list', { 'queryset': NonWgMailingList.objects.filter(status__gt=0) }),
|
||||
)
|
||||
urlpatterns += patterns('',
|
||||
(r'^nonwg_lists/submit/$', views.non_wg_wizard),
|
||||
(r'^request/$', views.list_req_wizard),
|
||||
(r'^nonwg_lists/s2/$', views.non_wg_submit),
|
||||
)
|
||||
|
|
|
@ -1 +1,72 @@
|
|||
# Create your views here.
|
||||
from forms import NonWgStep1, ListReqStep1, PickApprover, DeletionPickApprover, UrlMultiWidget
|
||||
from models import NonWgMailingList
|
||||
from ietf.idtracker.models import Areas
|
||||
from django import newforms as forms
|
||||
from django.shortcuts import render_to_response
|
||||
from ietf.contrib import wizard, form_decorator
|
||||
|
||||
nonwg_fields = {
|
||||
'id': None,
|
||||
'status': None,
|
||||
'ds_name': None,
|
||||
'ds_email': None,
|
||||
'msg_to_ad': None,
|
||||
}
|
||||
|
||||
nonwg_widgets = {
|
||||
'list_url': UrlMultiWidget(choices=(('http://', 'http://'), ('https://', 'https://'), ('mailto:', 'mailto:'))),
|
||||
'subscribe_url': UrlMultiWidget(choices=(('n/a', 'Not Applicable'), ('http://', 'http://'), ('https://', 'https://'))),
|
||||
}
|
||||
|
||||
nonwg_callback = form_decorator(fields=nonwg_fields, widgets=nonwg_widgets)
|
||||
|
||||
def gen_approval(approvers, parent):
|
||||
class BoundApproval(parent):
|
||||
_approvers = approvers
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(BoundApproval, self).__init__(self._approvers, *args, **kwargs)
|
||||
return BoundApproval
|
||||
|
||||
class NonWgWizard(wizard.Wizard):
|
||||
def get_template(self):
|
||||
return "mailinglists/nwg_wizard.html"
|
||||
def hash_failed(self, step):
|
||||
raise NotImplementedError("step %d hash failed" % step)
|
||||
def process_step(self, request, form, step):
|
||||
form.full_clean()
|
||||
if step == 0:
|
||||
if form.clean_data['add_edit'] == 'add':
|
||||
self.form_list.append(forms.form_for_model(NonWgMailingList, formfield_callback=nonwg_callback))
|
||||
elif form.clean_data['add_edit'] == 'edit':
|
||||
self.form_list.append(forms.form_for_instance(NonWgMailingList.objects.get(pk=form.clean_data['list_id']), formfield_callback=nonwg_callback))
|
||||
elif form.clean_data['add_edit'] == 'delete':
|
||||
list = NonWgMailingList.objects.get(pk=form.clean_data['list_id_delete'])
|
||||
self.form_list.append(gen_approval([ad.person_id for ad in list.area.areadirectors_set.all()], DeletionPickApprover))
|
||||
if step == 1:
|
||||
form0 = self.get_form(0, request.POST)
|
||||
form0.full_clean()
|
||||
add_edit = form0.clean_data['add_edit']
|
||||
if add_edit == 'add' or add_edit == 'edit':
|
||||
self.form_list.append(gen_approval([ad.person_id for ad in Areas.objects.get(area_acronym=form.clean_data['area']).areadirectors_set.all()], PickApprover))
|
||||
super(NonWgWizard, self).process_step(request, form, step)
|
||||
|
||||
def non_wg_wizard(request):
|
||||
wiz = NonWgWizard([ NonWgStep1 ])
|
||||
return wiz(request)
|
||||
|
||||
class ListReqWizard(wizard.Wizard):
|
||||
def get_template(self):
|
||||
return "mailinglists/nwg_wizard.html"
|
||||
def hash_failed(self, step):
|
||||
raise NotImplementedError("step %d hash failed" % step)
|
||||
def process_step(self, request, form, step):
|
||||
form.full_clean()
|
||||
super(ListReqWizard, self).process_step(request, form, step)
|
||||
|
||||
def list_req_wizard(request):
|
||||
wiz = ListReqWizard([ ListReqStep1 ])
|
||||
return wiz(request)
|
||||
|
||||
def non_wg_submit(request):
|
||||
form = NonWgStep1()
|
||||
return render_to_response('mailinglists/step1.html', { 'form': form })
|
||||
|
|
18
ietf/templates/mailinglists/nwg_wizard.html
Normal file
18
ietf/templates/mailinglists/nwg_wizard.html
Normal file
|
@ -0,0 +1,18 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block css %}
|
||||
ul.errorlist { color: red; border: 1px solid red; }
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<form action="." method="POST">
|
||||
FORM( {{ step }} ):<table> {{ form }} </table>
|
||||
|
||||
step_info : <input type="hidden" name="{{ step_field }}" value="{{ step }}" />
|
||||
|
||||
previous_fields: {{ previous_fields }}
|
||||
|
||||
<input type="submit">
|
||||
</form>
|
||||
|
||||
{% endblock %}
|
Loading…
Reference in a new issue