* Removed InternationalPhoneNumber class, instead using the form creation

callback to provide a RegexpField class.
 * Added checkbox for submitter contact information being the same as
   IETF contact information; with javascript support and validation
   support.
 * Cleaned out the old split_form() and mk_formatting_form() functions from
   ietf.utils.
 - Legacy-Id: 138
This commit is contained in:
Henrik Levkowetz 2007-05-18 15:50:30 +00:00
parent 8b2e90f212
commit 8d7053fc5c
5 changed files with 112 additions and 154 deletions

View file

@ -6,30 +6,6 @@ from django import newforms as forms
from ietf.idtracker.views import InternetDraft
from ietf.idtracker.models import Rfc
# ------------------------------------------------------------------------
# New field classes
phone_re = re.compile(r'^\+?[0-9 ]*(\([0-9]+\))?[0-9 -]+$')
class InternationalPhoneNumberField(models.CharField):
error_message = 'Phone numbers may have a leading "+", and otherwise only contain numbers [0-9], dash, space, and parentheses. '
def validate(self, field_data, all_data):
if not phone_re.search(field_data):
raise ValidationError, self.error_message + ' "%s" is invalid.' % field_data
def clean(self, value):
if value in EMPTY_VALUES:
return u''
self.validate(value, {})
return smart_unicode(value)
def formfield(self, **kwargs):
defaults = {'required': not self.blank, 'label': capfirst(self.verbose_name),
'help_text': self.help_text,
'error_message': self.error_message + "Enter a valid phone number."}
defaults.update(kwargs)
return forms.RegexField(phone_re, **defaults)
# ------------------------------------------------------------------------
# Models
@ -178,8 +154,8 @@ class IprContact(models.Model):
department = models.CharField(blank=True, maxlength=255)
address1 = models.CharField(blank=True, maxlength=255)
address2 = models.CharField(blank=True, maxlength=255)
telephone = InternationalPhoneNumberField(maxlength=25, core=True)
fax = InternationalPhoneNumberField(blank=True, maxlength=25)
telephone = models.CharField(maxlength=25, core=True)
fax = models.CharField(blank=True, maxlength=25)
email = models.EmailField(maxlength=255, core=True)
def __str__(self):
return self.name

View file

@ -1,9 +1,11 @@
import re
import models
from django.shortcuts import render_to_response as render
import django.newforms as forms
from django.utils.html import escape, linebreaks
import ietf.utils
import syslog
import django.newforms as forms
from django.shortcuts import render_to_response as render
from django.utils.html import escape, linebreaks
from ietf.contrib.form_decorator import form_decorator
from ietf.utils import log as log
def default(request):
"""Default page, with links to sub-pages"""
@ -83,7 +85,6 @@ def show(request, ipr_id=None):
ipr.discloser_identify = linebreaks(escape(ipr.discloser_identify))
ipr.comments = linebreaks(escape(ipr.comments))
ipr.other_notes = linebreaks(escape(ipr.other_notes))
opt = ipr.licensing_option
ipr.licensing_option = dict(models.LICENSE_CHOICES)[ipr.licensing_option]
ipr.selecttype = dict(models.SELECT_CHOICES)[ipr.selecttype]
if ipr.selectowned:
@ -99,14 +100,40 @@ def new(request, type):
"""Make a new IPR disclosure"""
debug = ""
# define callback methods for special field cases.
def ipr_detail_form_callback(field, **kwargs):
if field.name == "licensing_option":
return forms.IntegerField(widget=forms.RadioSelect(choices=models.LICENSE_CHOICES))
if field.name in ["selecttype", "selectowned"]:
return forms.IntegerField(widget=forms.RadioSelect(choices=((1, "YES"), (2, "NO"))))
return field.formfield(**kwargs)
def ipr_contact_form_callback(field, **kwargs):
phone_re = re.compile(r'^\+?[0-9 ]*(\([0-9]+\))?[0-9 -]+$')
error_message = """Phone numbers may have a leading "+", and otherwise only contain
numbers [0-9]; dash, period or space; parentheses, and an optional
extension number indicated by 'x'. """
if field.name == "telephone":
return forms.RegexField(phone_re, error_message=error_message, **kwargs)
if field.name == "fax":
return forms.RegexField(phone_re, error_message=error_message, required=False, **kwargs)
return field.formfield(**kwargs)
# Get a form class which renders fields using a given template
CustomForm = ietf.utils.makeFormattingForm(template="ipr/formfield.html")
BaseIprForm = forms.form_for_model(models.IprDetail, form=CustomForm, formfield_callback=detail_field_fixup)
BaseContactForm = forms.form_for_model(models.IprContact, form=CustomForm)
# Get base form classes for our models
BaseIprForm = forms.form_for_model(models.IprDetail, form=CustomForm, formfield_callback=ipr_detail_form_callback)
BaseContactForm = forms.form_for_model(models.IprContact, form=CustomForm, formfield_callback=ipr_contact_form_callback)
section_list = section_table[type]
section_list.update({"title":False, "new_intro":False, "form_intro":True, "form_submit":True, })
# Some subclassing:
# The contact form will be part of the IprForm, so it needs a widget.
# Define one.
class MultiformWidget(forms.Widget):
def value_from_datadict(self, data, name):
return data
@ -127,10 +154,18 @@ def new(request, type):
rfclist = forms.CharField(required=False)
draftlist = forms.CharField(required=False)
stdonly_license = forms.BooleanField(required=False)
ietf_contact_is_submitter = forms.BooleanField(required=False)
if "holder_contact" in section_list:
holder_contact = ContactForm(prefix="hold")
if "ietf_contact" in section_list:
ietf_contact = ContactForm(prefix="ietf")
if "submitter" in section_list:
submitter = ContactForm(prefix="subm")
def __init__(self, *args, **kw):
for contact in ["holder_contact", "ietf_contact", "submitter"]:
if contact in section_list:
self.base_fields[contact] = ContactForm(prefix=contact[:4], *args, **kw)
self.base_fields["ietf_contact_is_submitter"] = forms.BooleanField(required=False)
BaseIprForm.__init__(self, *args, **kw)
# Special validation code
def clean(self):
@ -138,10 +173,24 @@ def new(request, type):
# Submitter form filled in or 'same-as-ietf-contact' marked
# Only one of rfc, draft, and other info fields filled in
# RFC exists or draft exists and has right rev. or ...
if self.ietf_contact_is_submitter:
self.submitter = self.ietf_contact
pass
if request.method == 'POST':
form = IprForm(request.POST)
data = request.POST.copy()
if "ietf_contact_is_submitter" in data:
for subfield in ["name", "title", "department", "address1", "address2", "telephone", "fax", "email"]:
log("Fixing subfield subm_%s ..."%subfield)
try:
data["subm_%s"%subfield] = data["ietf_%s"%subfield]
log("Set to %s"%data["ietf_%s"%subfield])
except Exception, e:
log("Caught exception: %s"%e)
pass
form = IprForm(data)
if form.ietf_contact_is_submitter:
form.ietf_contact_is_submitter_checked = "checked"
if form.is_valid():
#instance = form.save()
#return HttpResponseRedirect("/ipr/ipr-%s" % instance.ipr_id)
@ -154,14 +203,9 @@ def new(request, type):
form = IprForm()
form.unbound_form = True
return render("ipr/details.html", {"ipr": form, "section_list":section_list, "debug": ""})
# ietf.utils.log(dir(form.ietf_contact_is_submitter))
return render("ipr/details.html", {"ipr": form, "section_list":section_list, "debug": debug})
def detail_field_fixup(field):
if field.name == "licensing_option":
return forms.IntegerField(widget=forms.RadioSelect(choices=models.LICENSE_CHOICES))
if field.name in ["selecttype", "selectowned"]:
return forms.IntegerField(widget=forms.RadioSelect(choices=((1, "YES"), (2, "NO"))))
return field.formfield()
# ---- Helper functions ------------------------------------------------------

View file

@ -129,7 +129,7 @@
</p>
<hr />
<form method="post">
<form name="form1" method="post">
{% endif %}
@ -348,6 +348,14 @@
</th>
</tr>
{% if ipr.submitter.name %}
{% if ipr.ietf_contact_is_submitter %}
<tr>
<td colspan="2">
Same as in Section III above:
<input type="checkbox" name="ietf_contact_is_submitter" onChange="toggle_submitter_info(this.checked);" {{ ipr.ietf_contact_is_submitter_checked }}></td>
</td>
</tr>
{% endif %}
<tr><td class="fixwidth">Name:</td> <td><b>{{ ipr.submitter.name }}</b></td></tr>
<tr><td class="fixwidth">Title:</td> <td><b>{{ ipr.submitter.title }}</b></td></tr>
<tr><td class="fixwidth">Department:</td> <td><b>{{ ipr.submitter.department }}</b></td></tr>

View file

@ -10,12 +10,12 @@
padding:2px;
border-width:1px;
border-style:solid;
border-color:305076;
border-color:#305076;
}
.ipr th { border: 0px; margin: 0px; padding: 4px; }
.ipr td { border: 0px; margin: 0px; padding: 4px; }
td.fixwidth { width: 14ex; }
.ipr ul { padding-left: -2ex; list-style-type: none; }
.ipr ul { list-style-type: none; }
h4.ipr { text-align: center; }
input { width: 72ex; font-family: sans-serif; font-size: 11pt; font-weight: normal; }
input[type="radio"] { width: auto; }
@ -25,3 +25,38 @@
.required { color: red; float: right; padding-top: 0.7ex; font-size: 130%; }
.errorlist { background: red; padding: 0 0 0 2px; border: 0px; margin: 0px; }
</style>
<script type="text/javascript">
function toggle_submitter_info (checked) {
if (checked) {
document.form1.subm_name.value = document.form1.ietf_name.value;
document.form1.subm_title.value = document.form1.ietf_title.value;
document.form1.subm_department.value = document.form1.ietf_department.value;
document.form1.subm_telephone.value = document.form1.ietf_telephone.value;
document.form1.subm_fax.value = document.form1.ietf_fax.value;
document.form1.subm_email.value = document.form1.ietf_email.value;
document.form1.subm_address1.value = document.form1.ietf_address1.value;
document.form1.subm_address2.value = document.form1.ietf_address2.value;
} else {
document.form1.subm_name.value = "";
document.form1.subm_title.value = "";
document.form1.subm_department.value = "";
document.form1.subm_telephone.value = "";
document.form1.subm_fax.value = "";
document.form1.subm_email.value = "";
document.form1.subm_address1.value = "";
document.form1.subm_address2.value = "";
}
document.form1.subm_name.disabled = checked;
document.form1.subm_title.disabled = checked;
document.form1.subm_department.disabled = checked;
document.form1.subm_telephone.disabled = checked;
document.form1.subm_fax.disabled = checked;
document.form1.subm_email.disabled = checked;
document.form1.subm_address1.disabled = checked;
document.form1.subm_address2.disabled = checked;
return true;
}
</script>

View file

@ -52,111 +52,6 @@ class FKAsOneToOne(object):
setattr(instance, self.field, value)
def split_form(html, blocks):
"""Split the rendering of a form into a dictionary of named blocks.
Takes the html of the rendered form as the first argument.
Expects a dictionary as the second argument, with desired block
name and a field specification as key:value pairs.
The field specification can be either a list of field names, or
a string with the field names separated by whitespace.
The return value is a new dictionary, with the same keys as the
block specification dictionary, and the form rendering matching
the specified keys as the value.
Any line in the rendered form which doesn't match any block's
field list will cause an exception to be raised.
"""
import re
output = dict([(block,[]) for block in blocks])
# handle field lists in string form
for block in blocks:
if type(blocks[block]) == type(""):
blocks[block] = blocks[block].split()
# collapse radio button html to one line
html = re.sub('\n(.*type="radio".*\n)', "\g<1>", html)
html = re.sub('(?m)^(.*type="radio".*)\n', "\g<1>", html)
for line in html.split('\n'):
found = False
for block in blocks:
for field in blocks[block]:
if ('name="%s"' % field) in line:
output[block].append(line)
found = True
if not found:
raise LookupError("Could not place line in any section: '%s'" % line)
for block in output:
output[block] = "\n".join(output[block])
return output
def mk_formatting_form(format="<span>%(label)s</span><span><ul>%(errors)s</ul>%(field)s%(help_text)s</span>",
labelfmt="%s:", fieldfmt="%s", errfmt="<li>%s</li>", error_wrap="<ul>%s</ul>", helpfmt="%s"):
"""Create a form class which formats its fields using the provided format string(s).
The format string may use these format specifications:
%(label)s
%(errors)s
%(field)s
%(help_text)s
The individual sub-formats must contain "%s" if defined.
"""
class FormattingForm(forms.BaseForm):
_format = format
_labelfmt = labelfmt
_fieldfmt = fieldfmt
_errfmt = errfmt
_errwrap = error_wrap
_helpfmt = helpfmt
def __getitem__(self, name):
"Returns a BoundField with the given name."
# syslog.syslog("FormattingForm.__getitem__(%s)" % (name))
try:
field = self.fields[name]
except KeyError:
# syslog.syslog("Exception: FormattingForm.__getitem__: Key %r not found" % (name))
raise KeyError('Key %r not found in Form' % name)
if not isinstance(field, forms.fields.Field):
return field
try:
bf = forms.forms.BoundField(self, field, name)
except Exception, e:
# syslog.syslog("Exception: FormattingForm.__getitem__: %s" % (e))
raise Exception(e)
try:
error_txt = "".join([self._errfmt % escape(error) for error in bf.errors])
error_txt = error_txt and self._errwrap % error_txt
label_txt = bf.label and self._labelfmt % bf.label_tag(escape(bf.label)) or ''
field_txt = self._fieldfmt % unicode(bf)
help_txt = field.help_text and self._helpfmt % field.help_text or u''
except Exception, e:
# syslog.syslog("Exception: FormattingForm.__getitem__: %s" % (e))
raise Exception(e)
return self._format % {"label":label_txt, "errors":error_txt, "field":field_txt, "help_text":help_txt}
def add_prefix(self, field_name):
return self.prefix and ('%s_%s' % (self.prefix, field_name)) or field_name
# syslog.syslog("Created new FormattingForm class: %s" % FormattingForm)
return FormattingForm
def makeFormattingForm(template=None):
"""Create a form class which formats its fields using the provided template