Skip to content

Commit 8d7053f

Browse files
committed
* 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
1 parent 8b2e90f commit 8d7053f

5 files changed

Lines changed: 111 additions & 153 deletions

File tree

ietf/ipr/models.py

Lines changed: 2 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -6,30 +6,6 @@
66
from ietf.idtracker.views import InternetDraft
77
from ietf.idtracker.models import Rfc
88

9-
# ------------------------------------------------------------------------
10-
# New field classes
11-
12-
phone_re = re.compile(r'^\+?[0-9 ]*(\([0-9]+\))?[0-9 -]+$')
13-
class InternationalPhoneNumberField(models.CharField):
14-
error_message = 'Phone numbers may have a leading "+", and otherwise only contain numbers [0-9], dash, space, and parentheses. '
15-
def validate(self, field_data, all_data):
16-
if not phone_re.search(field_data):
17-
raise ValidationError, self.error_message + ' "%s" is invalid.' % field_data
18-
19-
def clean(self, value):
20-
if value in EMPTY_VALUES:
21-
return u''
22-
self.validate(value, {})
23-
return smart_unicode(value)
24-
25-
def formfield(self, **kwargs):
26-
defaults = {'required': not self.blank, 'label': capfirst(self.verbose_name),
27-
'help_text': self.help_text,
28-
'error_message': self.error_message + "Enter a valid phone number."}
29-
defaults.update(kwargs)
30-
return forms.RegexField(phone_re, **defaults)
31-
32-
339
# ------------------------------------------------------------------------
3410
# Models
3511

@@ -178,8 +154,8 @@ class IprContact(models.Model):
178154
department = models.CharField(blank=True, maxlength=255)
179155
address1 = models.CharField(blank=True, maxlength=255)
180156
address2 = models.CharField(blank=True, maxlength=255)
181-
telephone = InternationalPhoneNumberField(maxlength=25, core=True)
182-
fax = InternationalPhoneNumberField(blank=True, maxlength=25)
157+
telephone = models.CharField(maxlength=25, core=True)
158+
fax = models.CharField(blank=True, maxlength=25)
183159
email = models.EmailField(maxlength=255, core=True)
184160
def __str__(self):
185161
return self.name

ietf/ipr/views.py

Lines changed: 63 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1+
import re
12
import models
2-
from django.shortcuts import render_to_response as render
3+
import ietf.utils
34
import django.newforms as forms
5+
from django.shortcuts import render_to_response as render
46
from django.utils.html import escape, linebreaks
5-
import ietf.utils
6-
import syslog
7+
from ietf.contrib.form_decorator import form_decorator
8+
from ietf.utils import log as log
79

810
def default(request):
911
"""Default page, with links to sub-pages"""
@@ -83,7 +85,6 @@ def show(request, ipr_id=None):
8385
ipr.discloser_identify = linebreaks(escape(ipr.discloser_identify))
8486
ipr.comments = linebreaks(escape(ipr.comments))
8587
ipr.other_notes = linebreaks(escape(ipr.other_notes))
86-
opt = ipr.licensing_option
8788
ipr.licensing_option = dict(models.LICENSE_CHOICES)[ipr.licensing_option]
8889
ipr.selecttype = dict(models.SELECT_CHOICES)[ipr.selecttype]
8990
if ipr.selectowned:
@@ -99,49 +100,97 @@ def new(request, type):
99100
"""Make a new IPR disclosure"""
100101
debug = ""
101102

103+
# define callback methods for special field cases.
104+
def ipr_detail_form_callback(field, **kwargs):
105+
if field.name == "licensing_option":
106+
return forms.IntegerField(widget=forms.RadioSelect(choices=models.LICENSE_CHOICES))
107+
if field.name in ["selecttype", "selectowned"]:
108+
return forms.IntegerField(widget=forms.RadioSelect(choices=((1, "YES"), (2, "NO"))))
109+
return field.formfield(**kwargs)
110+
111+
def ipr_contact_form_callback(field, **kwargs):
112+
phone_re = re.compile(r'^\+?[0-9 ]*(\([0-9]+\))?[0-9 -]+$')
113+
error_message = """Phone numbers may have a leading "+", and otherwise only contain
114+
numbers [0-9]; dash, period or space; parentheses, and an optional
115+
extension number indicated by 'x'. """
116+
117+
if field.name == "telephone":
118+
return forms.RegexField(phone_re, error_message=error_message, **kwargs)
119+
if field.name == "fax":
120+
return forms.RegexField(phone_re, error_message=error_message, required=False, **kwargs)
121+
return field.formfield(**kwargs)
122+
123+
# Get a form class which renders fields using a given template
102124
CustomForm = ietf.utils.makeFormattingForm(template="ipr/formfield.html")
103-
BaseIprForm = forms.form_for_model(models.IprDetail, form=CustomForm, formfield_callback=detail_field_fixup)
104-
BaseContactForm = forms.form_for_model(models.IprContact, form=CustomForm)
125+
126+
# Get base form classes for our models
127+
BaseIprForm = forms.form_for_model(models.IprDetail, form=CustomForm, formfield_callback=ipr_detail_form_callback)
128+
BaseContactForm = forms.form_for_model(models.IprContact, form=CustomForm, formfield_callback=ipr_contact_form_callback)
105129

106130
section_list = section_table[type]
107131
section_list.update({"title":False, "new_intro":False, "form_intro":True, "form_submit":True, })
108132

109133
# Some subclassing:
134+
135+
# The contact form will be part of the IprForm, so it needs a widget.
136+
# Define one.
110137
class MultiformWidget(forms.Widget):
111-
def value_from_datadict(self, data, name):
112-
return data
113-
138+
def value_from_datadict(self, data, name):
139+
return data
140+
114141
class ContactForm(BaseContactForm):
115142
widget = MultiformWidget()
116-
143+
117144
def add_prefix(self, field_name):
118145
return self.prefix and ('%s_%s' % (self.prefix, field_name)) or field_name
119146
def clean(self, *value):
120147
if value:
121148
return self.full_clean()
122149
else:
123150
return self.clean_data
124-
151+
125152
class IprForm(BaseIprForm):
126153
holder_contact = None
127154
rfclist = forms.CharField(required=False)
128155
draftlist = forms.CharField(required=False)
129156
stdonly_license = forms.BooleanField(required=False)
157+
ietf_contact_is_submitter = forms.BooleanField(required=False)
158+
if "holder_contact" in section_list:
159+
holder_contact = ContactForm(prefix="hold")
160+
if "ietf_contact" in section_list:
161+
ietf_contact = ContactForm(prefix="ietf")
162+
if "submitter" in section_list:
163+
submitter = ContactForm(prefix="subm")
130164
def __init__(self, *args, **kw):
131165
for contact in ["holder_contact", "ietf_contact", "submitter"]:
132166
if contact in section_list:
133167
self.base_fields[contact] = ContactForm(prefix=contact[:4], *args, **kw)
168+
self.base_fields["ietf_contact_is_submitter"] = forms.BooleanField(required=False)
134169
BaseIprForm.__init__(self, *args, **kw)
135170
# Special validation code
136171
def clean(self):
137172
# Required:
138173
# Submitter form filled in or 'same-as-ietf-contact' marked
139174
# Only one of rfc, draft, and other info fields filled in
140175
# RFC exists or draft exists and has right rev. or ...
176+
if self.ietf_contact_is_submitter:
177+
self.submitter = self.ietf_contact
141178
pass
142179

143180
if request.method == 'POST':
144-
form = IprForm(request.POST)
181+
data = request.POST.copy()
182+
if "ietf_contact_is_submitter" in data:
183+
for subfield in ["name", "title", "department", "address1", "address2", "telephone", "fax", "email"]:
184+
log("Fixing subfield subm_%s ..."%subfield)
185+
try:
186+
data["subm_%s"%subfield] = data["ietf_%s"%subfield]
187+
log("Set to %s"%data["ietf_%s"%subfield])
188+
except Exception, e:
189+
log("Caught exception: %s"%e)
190+
pass
191+
form = IprForm(data)
192+
if form.ietf_contact_is_submitter:
193+
form.ietf_contact_is_submitter_checked = "checked"
145194
if form.is_valid():
146195
#instance = form.save()
147196
#return HttpResponseRedirect("/ipr/ipr-%s" % instance.ipr_id)
@@ -154,14 +203,9 @@ def clean(self):
154203
form = IprForm()
155204
form.unbound_form = True
156205

157-
return render("ipr/details.html", {"ipr": form, "section_list":section_list, "debug": ""})
206+
# ietf.utils.log(dir(form.ietf_contact_is_submitter))
207+
return render("ipr/details.html", {"ipr": form, "section_list":section_list, "debug": debug})
158208

159-
def detail_field_fixup(field):
160-
if field.name == "licensing_option":
161-
return forms.IntegerField(widget=forms.RadioSelect(choices=models.LICENSE_CHOICES))
162-
if field.name in ["selecttype", "selectowned"]:
163-
return forms.IntegerField(widget=forms.RadioSelect(choices=((1, "YES"), (2, "NO"))))
164-
return field.formfield()
165209

166210

167211
# ---- Helper functions ------------------------------------------------------

ietf/templates/ipr/details.html

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ <h4 class="ipr">The Patent Disclosure and Licensing Declaration Template for {{
129129

130130
</p>
131131
<hr />
132-
<form method="post">
132+
<form name="form1" method="post">
133133
{% endif %}
134134

135135

@@ -348,6 +348,14 @@ <h4 class="ipr">The Patent Disclosure and Licensing Declaration Template for {{
348348
</th>
349349
</tr>
350350
{% if ipr.submitter.name %}
351+
{% if ipr.ietf_contact_is_submitter %}
352+
<tr>
353+
<td colspan="2">
354+
Same as in Section III above:
355+
<input type="checkbox" name="ietf_contact_is_submitter" onChange="toggle_submitter_info(this.checked);" {{ ipr.ietf_contact_is_submitter_checked }}></td>
356+
</td>
357+
</tr>
358+
{% endif %}
351359
<tr><td class="fixwidth">Name:</td> <td><b>{{ ipr.submitter.name }}</b></td></tr>
352360
<tr><td class="fixwidth">Title:</td> <td><b>{{ ipr.submitter.title }}</b></td></tr>
353361
<tr><td class="fixwidth">Department:</td> <td><b>{{ ipr.submitter.department }}</b></td></tr>

ietf/templates/ipr/style.html

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,12 @@
1010
padding:2px;
1111
border-width:1px;
1212
border-style:solid;
13-
border-color:305076;
13+
border-color:#305076;
1414
}
1515
.ipr th { border: 0px; margin: 0px; padding: 4px; }
1616
.ipr td { border: 0px; margin: 0px; padding: 4px; }
1717
td.fixwidth { width: 14ex; }
18-
.ipr ul { padding-left: -2ex; list-style-type: none; }
18+
.ipr ul { list-style-type: none; }
1919
h4.ipr { text-align: center; }
2020
input { width: 72ex; font-family: sans-serif; font-size: 11pt; font-weight: normal; }
2121
input[type="radio"] { width: auto; }
@@ -25,3 +25,38 @@
2525
.required { color: red; float: right; padding-top: 0.7ex; font-size: 130%; }
2626
.errorlist { background: red; padding: 0 0 0 2px; border: 0px; margin: 0px; }
2727
</style>
28+
29+
<script type="text/javascript">
30+
function toggle_submitter_info (checked) {
31+
if (checked) {
32+
document.form1.subm_name.value = document.form1.ietf_name.value;
33+
document.form1.subm_title.value = document.form1.ietf_title.value;
34+
document.form1.subm_department.value = document.form1.ietf_department.value;
35+
document.form1.subm_telephone.value = document.form1.ietf_telephone.value;
36+
document.form1.subm_fax.value = document.form1.ietf_fax.value;
37+
document.form1.subm_email.value = document.form1.ietf_email.value;
38+
document.form1.subm_address1.value = document.form1.ietf_address1.value;
39+
document.form1.subm_address2.value = document.form1.ietf_address2.value;
40+
} else {
41+
document.form1.subm_name.value = "";
42+
document.form1.subm_title.value = "";
43+
document.form1.subm_department.value = "";
44+
document.form1.subm_telephone.value = "";
45+
document.form1.subm_fax.value = "";
46+
document.form1.subm_email.value = "";
47+
document.form1.subm_address1.value = "";
48+
document.form1.subm_address2.value = "";
49+
}
50+
document.form1.subm_name.disabled = checked;
51+
document.form1.subm_title.disabled = checked;
52+
document.form1.subm_department.disabled = checked;
53+
document.form1.subm_telephone.disabled = checked;
54+
document.form1.subm_fax.disabled = checked;
55+
document.form1.subm_email.disabled = checked;
56+
document.form1.subm_address1.disabled = checked;
57+
document.form1.subm_address2.disabled = checked;
58+
59+
return true;
60+
}
61+
</script>
62+

ietf/utils/__init__.py

Lines changed: 0 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -52,111 +52,6 @@ def __set__(self, instance, value):
5252
setattr(instance, self.field, value)
5353

5454

55-
56-
57-
def split_form(html, blocks):
58-
"""Split the rendering of a form into a dictionary of named blocks.
59-
60-
Takes the html of the rendered form as the first argument.
61-
62-
Expects a dictionary as the second argument, with desired block
63-
name and a field specification as key:value pairs.
64-
65-
The field specification can be either a list of field names, or
66-
a string with the field names separated by whitespace.
67-
68-
The return value is a new dictionary, with the same keys as the
69-
block specification dictionary, and the form rendering matching
70-
the specified keys as the value.
71-
72-
Any line in the rendered form which doesn't match any block's
73-
field list will cause an exception to be raised.
74-
"""
75-
import re
76-
output = dict([(block,[]) for block in blocks])
77-
# handle field lists in string form
78-
for block in blocks:
79-
if type(blocks[block]) == type(""):
80-
blocks[block] = blocks[block].split()
81-
82-
# collapse radio button html to one line
83-
html = re.sub('\n(.*type="radio".*\n)', "\g<1>", html)
84-
html = re.sub('(?m)^(.*type="radio".*)\n', "\g<1>", html)
85-
86-
for line in html.split('\n'):
87-
found = False
88-
for block in blocks:
89-
for field in blocks[block]:
90-
if ('name="%s"' % field) in line:
91-
output[block].append(line)
92-
found = True
93-
if not found:
94-
raise LookupError("Could not place line in any section: '%s'" % line)
95-
96-
for block in output:
97-
output[block] = "\n".join(output[block])
98-
99-
return output
100-
101-
def mk_formatting_form(format="<span>%(label)s</span><span><ul>%(errors)s</ul>%(field)s%(help_text)s</span>",
102-
labelfmt="%s:", fieldfmt="%s", errfmt="<li>%s</li>", error_wrap="<ul>%s</ul>", helpfmt="%s"):
103-
"""Create a form class which formats its fields using the provided format string(s).
104-
105-
The format string may use these format specifications:
106-
%(label)s
107-
%(errors)s
108-
%(field)s
109-
%(help_text)s
110-
111-
The individual sub-formats must contain "%s" if defined.
112-
"""
113-
class FormattingForm(forms.BaseForm):
114-
_format = format
115-
_labelfmt = labelfmt
116-
_fieldfmt = fieldfmt
117-
_errfmt = errfmt
118-
_errwrap = error_wrap
119-
_helpfmt = helpfmt
120-
def __getitem__(self, name):
121-
"Returns a BoundField with the given name."
122-
# syslog.syslog("FormattingForm.__getitem__(%s)" % (name))
123-
try:
124-
field = self.fields[name]
125-
except KeyError:
126-
# syslog.syslog("Exception: FormattingForm.__getitem__: Key %r not found" % (name))
127-
raise KeyError('Key %r not found in Form' % name)
128-
129-
if not isinstance(field, forms.fields.Field):
130-
return field
131-
132-
try:
133-
bf = forms.forms.BoundField(self, field, name)
134-
except Exception, e:
135-
# syslog.syslog("Exception: FormattingForm.__getitem__: %s" % (e))
136-
raise Exception(e)
137-
138-
try:
139-
error_txt = "".join([self._errfmt % escape(error) for error in bf.errors])
140-
error_txt = error_txt and self._errwrap % error_txt
141-
label_txt = bf.label and self._labelfmt % bf.label_tag(escape(bf.label)) or ''
142-
field_txt = self._fieldfmt % unicode(bf)
143-
help_txt = field.help_text and self._helpfmt % field.help_text or u''
144-
145-
except Exception, e:
146-
# syslog.syslog("Exception: FormattingForm.__getitem__: %s" % (e))
147-
raise Exception(e)
148-
149-
return self._format % {"label":label_txt, "errors":error_txt, "field":field_txt, "help_text":help_txt}
150-
151-
def add_prefix(self, field_name):
152-
return self.prefix and ('%s_%s' % (self.prefix, field_name)) or field_name
153-
154-
155-
# syslog.syslog("Created new FormattingForm class: %s" % FormattingForm)
156-
157-
return FormattingForm
158-
159-
16055
def makeFormattingForm(template=None):
16156
"""Create a form class which formats its fields using the provided template
16257

0 commit comments

Comments
 (0)