Skip to content

Commit a2cbb76

Browse files
committed
Date picker and file attachments. See ietf-tools#342
- Legacy-Id: 2373
1 parent 547aee8 commit a2cbb76

25 files changed

Lines changed: 859 additions & 25 deletions

ietf/liaisons/forms.py

Lines changed: 56 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,81 @@
11
from django import forms
22
from django.conf import settings
3+
from django.forms.util import ErrorList
34
from django.template.loader import render_to_string
45

56
from ietf.liaisons.accounts import (can_add_outgoing_liaison, can_add_incoming_liaison,
67
get_person_for_user)
78
from ietf.liaisons.models import LiaisonDetail
89
from ietf.liaisons.utils import IETFHierarchyManager
9-
from ietf.liaisons.widgets import FromWidget, ReadOnlyWidget
10+
from ietf.liaisons.widgets import FromWidget, ReadOnlyWidget, ButtonWidget
1011

1112

1213
class LiaisonForm(forms.ModelForm):
1314

1415
from_field = forms.ChoiceField(widget=FromWidget, label=u'From')
1516
replyto = forms.CharField(label=u'Reply to')
1617
organization = forms.ChoiceField()
17-
to_poc = forms.CharField(widget=ReadOnlyWidget, label="POC")
18-
cc1 = forms.CharField(widget=ReadOnlyWidget, label="CC")
18+
to_poc = forms.CharField(widget=ReadOnlyWidget, label="POC", required=False)
19+
cc1 = forms.CharField(widget=ReadOnlyWidget, label="CC", required=False)
1920
purpose_text = forms.CharField(widget=forms.Textarea, label='Other purpose')
2021
deadline_date = forms.DateField(label='Deadline')
22+
title = forms.CharField(label=u'Title')
23+
attachments = forms.CharField(label='Attachments', widget=ReadOnlyWidget, initial='No files attached', required=False)
24+
attach_title = forms.CharField(label='Title', required=False)
25+
attach_file = forms.FileField(label='File', required=False)
26+
attach_button = forms.CharField(label='',
27+
widget=ButtonWidget(label='Attach', show_on='id_attachments',
28+
require=['id_attach_title', 'id_attach_file'],
29+
required_label='title and file'),
30+
required=False)
2131

2232
fieldsets = (('From', ('from_field', 'replyto')),
2333
('To', ('organization', 'to_poc')),
2434
('Other email addresses', ('response_contact', 'technical_contact', 'cc1')),
2535
('Purpose', ('purpose', 'purpose_text', 'deadline_date')),
26-
('Body', ('body', )),
36+
('Liaison Statement', ('title', 'body', 'attachments')),
37+
('Add attachment', ('attach_title', 'attach_file', 'attach_button')),
2738
)
2839

2940
class Meta:
3041
model = LiaisonDetail
3142

3243
class Media:
3344
js = ("/js/jquery-1.4.2.min.js",
45+
"/js/jquery-ui-1.8.2.custom.min.js",
3446
"/js/liaisons.js", )
3547

36-
css = {'all': ("/css/liaisons.css", )}
48+
css = {'all': ("/css/liaisons.css",
49+
"/css/jquery-ui-themes/jquery-ui-1.8.2.custom.css")}
3750

3851
def __init__(self, user, *args, **kwargs):
52+
self.person = get_person_for_user(user)
53+
if kwargs.get('data', None):
54+
kwargs['data'].update({'person': self.person.pk})
3955
super(LiaisonForm, self).__init__(*args, **kwargs)
4056
self.hm = IETFHierarchyManager()
41-
self.person = get_person_for_user(user)
4257
self.set_from_field()
4358
self.set_replyto_field()
4459
self.set_organization_field()
4560

4661
def __unicode__(self):
4762
return self.as_div()
4863

64+
def set_purpose_required_fields(self):
65+
purpose = self.data.get('purpose', None)
66+
if purpose == '5':
67+
self.fields['purpose_text'].required=True
68+
else:
69+
self.fields['purpose_text'].required=False
70+
if purpose in ['1', '2']:
71+
self.fields['deadline_date'].required=True
72+
else:
73+
self.fields['deadline_date'].required=False
74+
75+
def reset_purpose_required_fields(self):
76+
self.fields['purpose_text'].required=True
77+
self.fields['deadline_date'].required=True
78+
4979
def set_from_field(self):
5080
assert NotImplemented
5181

@@ -73,6 +103,23 @@ def get_fieldsets(self):
73103
continue
74104
yield fieldset_dict
75105

106+
def full_clean(self):
107+
self.set_purpose_required_fields()
108+
super(LiaisonForm, self).full_clean()
109+
self.reset_purpose_required_fields()
110+
111+
def has_attachments(self):
112+
for key in self.files.keys():
113+
if key.startswith('attach_file_') and key.replace('file', 'title') in self.data.keys():
114+
return True
115+
return False
116+
117+
def clean(self):
118+
if not self.cleaned_data.get('body', None) and not self.has_attachments():
119+
self._errors['body'] = ErrorList([u'You must provide a body or attachment files'])
120+
self._errors['attachments'] = ErrorList([u'You must provide a body or attachment files'])
121+
return self.cleaned_data
122+
76123

77124
class IncomingLiaisonForm(LiaisonForm):
78125

@@ -96,10 +143,10 @@ def set_organization_field(self):
96143
pass
97144

98145

99-
def liaison_form_factory(request):
146+
def liaison_form_factory(request, **kwargs):
100147
user = request.user
101148
if can_add_incoming_liaison(user):
102-
return IncomingLiaisonForm(user)
149+
return IncomingLiaisonForm(user, **kwargs)
103150
elif can_add_outgoing_liaison(user):
104-
return OutgoingLiaisonForm(user)
151+
return OutgoingLiaisonForm(user, **kwargs)
105152
return None

ietf/liaisons/views.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,14 @@
1313

1414
@can_submit_liaison
1515
def add_liaison(request):
16-
form = liaison_form_factory(request)
16+
if request.method == 'POST':
17+
form = liaison_form_factory(request, data=request.POST.copy(),
18+
files = request.FILES)
19+
if form.is_valid():
20+
#form.save()
21+
pass
22+
else:
23+
form = liaison_form_factory(request)
1724

1825
return render_to_response(
1926
'liaisons/liaisondetail_edit.html',

ietf/liaisons/widgets.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,24 @@ class ReadOnlyWidget(Widget):
1919
def render(self, name, value, attrs=None):
2020
html = u'<div id="id_%s">%s</div>' % (name, value or '')
2121
return mark_safe(html)
22+
23+
24+
class ButtonWidget(Widget):
25+
26+
def __init__(self, *args, **kwargs):
27+
self.label = kwargs.pop('label', None)
28+
self.show_on = kwargs.pop('show_on', None)
29+
self.require = kwargs.pop('require', None)
30+
self.required_label = kwargs.pop('required_label', None)
31+
super(ButtonWidget, self).__init__(*args, **kwargs)
32+
33+
def render(self, name, value, attrs=None):
34+
html = u'<span style="display: none" class="showAttachsOn">%s</span>' % self.show_on
35+
html += u'<span style="display: none" class="attachEnabledLabel">%s</span>' % self.label
36+
if self.require:
37+
for i in self.require:
38+
html += u'<span style="display: none" class="attachRequiredField">%s</span>' % i
39+
required_str = u'Please fill %s to attach a new file' % self.required_label
40+
html += u'<span style="display: none" class="attachDisabledLabel">%s</span>' % required_str
41+
html += u'<input type="button" class="addAttachmentWidget" value="%s" />' % self.label
42+
return mark_safe(html)

ietf/templates/liaisons/liaisondetail_edit.html

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@
1010
{% block content %}
1111
<h1>Send Liaison Statement</h1>
1212

13+
<ul>
14+
<li>If you wish to submit your liaison statement by e-mail, then please send it to <a href="mailto:statements@ietf.org">statements@ietf.org</a></li>
15+
<li>Fields marked with <span class="requiredField">*</span> are required. For detailed descriptions of the fields see <a href="https://datatracker.ietf.org/liaison/help/fields/">Field help</a></li>
16+
</ul>
17+
1318
{{ form }}
1419

1520
{% endblock %}
Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{% load i18n %}
22

3-
<form class="liaisonform" method="post" action="">
3+
<form class="liaisonform" method="post" action="" enctype="multipart/form-data">
44

55
<div class="formconfig" style="display: none;">
66
{% block formconfig %}
@@ -10,6 +10,11 @@
1010
</div>
1111

1212
<div class="baseform">
13+
{% if form.errors %}
14+
<div class="formErrors">
15+
Please correct the errors below.
16+
</div>
17+
{% endif %}
1318
{% for fieldset in form.get_fieldsets %}
1419
{% if fieldset.name %}
1520
<div class="fieldset">
@@ -18,15 +23,16 @@ <h2>{{ fieldset.name }}</h2>
1823

1924
{% for field in fieldset.fields %}
2025
<div id="baseform-fieldname-{{ field.html_name }}"
21-
class="{% if field.errors %}error {% endif %}field BaseFormStringWidget{% if field.field.column_style %} {{ field.field.column_style }}{% endif %}">
22-
<label for="id_{{ field.html_name }}">{{ field.label }}</label>
26+
class="{% if field.errors %}fieldError {% endif %}field BaseFormStringWidget{% if field.field.column_style %} {{ field.field.column_style }}{% endif %}">
27+
<label for="id_{{ field.html_name }}">{{ field.label }}
2328
{% if field.field.required %}
24-
<span class="fieldRequired" title="Required"></span>
29+
<span class="fieldRequired" title="Required">*</span>
2530
{% endif %}
31+
</label>
2632
<div class="fieldWidget">
27-
{{ field.errors }}
2833
<div id="{{ field.html_name }}_help" class="formHelp"> {{ field.help_text }}</div>
2934
{{ field }}
35+
{{ field.errors }}
3036
</div>
3137
<div class="endfield"></div>
3238
</div>
@@ -37,10 +43,10 @@ <h2>{{ fieldset.name }}</h2>
3743
{% endif %}
3844
{% endfor %}
3945

46+
<div class="submitrow">
47+
<input type="submit" value="Send and Post" name="send" />
48+
<input type="submit" value="Post Only" name="post_only" />
49+
</div>
4050
</div>
4151

42-
<div class="submitrow">
43-
<input type="submit" value="Send and Post" name="send" />
44-
<input type="submit" value="Post Only" name="post_only" />
45-
</div>
4652
</form>
1.52 KB
Loading
180 Bytes
Loading
182 Bytes
Loading
124 Bytes
Loading
123 Bytes
Loading

0 commit comments

Comments
 (0)