Skip to content

Commit 709181c

Browse files
committed
Outgoing liaison form with automatic filled fields. See ietf-tools#343
- Legacy-Id: 2428
1 parent fbbf182 commit 709181c

File tree

5 files changed

+161
-50
lines changed

5 files changed

+161
-50
lines changed

ietf/liaisons/forms.py

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,13 @@ class LiaisonForm(forms.ModelForm):
3232
required_label='title and file'),
3333
required=False)
3434

35-
fieldsets = (('From', ('from_field', 'replyto')),
35+
fieldsets = [('From', ('from_field', 'replyto')),
3636
('To', ('organization', 'to_poc')),
3737
('Other email addresses', ('response_contact', 'technical_contact', 'cc1')),
3838
('Purpose', ('purpose', 'purpose_text', 'deadline_date')),
3939
('Liaison Statement', ('title', 'body', 'attachments')),
4040
('Add attachment', ('attach_title', 'attach_file', 'attach_button')),
41-
)
41+
]
4242

4343
class Meta:
4444
model = LiaisonDetail
@@ -129,7 +129,10 @@ def get_from_entity(self):
129129

130130
def get_to_entity(self):
131131
organization_key = self.cleaned_data.get('organization')
132-
return self.hm.get_entity_by_key(organization_key)
132+
organization = self.hm.get_entity_by_key(organization_key)
133+
if not organization and self.cleaned_data.get('other_organization', None):
134+
return self.cleaned_data.get('other_organization')
135+
return organization
133136

134137
def save(self, *args, **kwargs):
135138
now = datetime.datetime.now()
@@ -181,17 +184,22 @@ def set_organization_field(self):
181184

182185
class OutgoingLiaisonForm(LiaisonForm):
183186

187+
to_poc = forms.CharField(label="POC", required=True)
188+
other_organization = forms.CharField(label="Other SDO", required=True)
189+
184190
def set_from_field(self):
185-
pass
191+
self.fields['from_field'].choices = self.hm.get_entities_for_person(self.person)
192+
self.fields['from_field'].widget.submitter = unicode(self.person)
186193

187194
def set_organization_field(self):
188-
pass
195+
self.fields['organization'].choices = self.hm.get_all_outgoing_entities()
196+
self.fieldsets[1] = ('To', ('organization', 'other_organization', 'to_poc'))
189197

190198

191199
def liaison_form_factory(request, **kwargs):
192200
user = request.user
193-
if can_add_incoming_liaison(user):
194-
return IncomingLiaisonForm(user, **kwargs)
195-
elif can_add_outgoing_liaison(user):
201+
if can_add_outgoing_liaison(user):
196202
return OutgoingLiaisonForm(user, **kwargs)
203+
elif can_add_incoming_liaison(user):
204+
return IncomingLiaisonForm(user, **kwargs)
197205
return None

ietf/liaisons/utils.py

Lines changed: 137 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from ietf.idtracker.models import Area, IETFWG
22
from ietf.liaisons.models import SDOs
3+
from ietf.liaisons.accounts import is_ietfchair, is_iabchair, is_iab_executive_director
34

45
IETFCHAIR = {'name': u'The IETF Chair', 'address': u'chair@ietf.org'}
56
IESG = {'name': u'The IESG', 'address': u'iesg@ietf.org'}
@@ -18,12 +19,10 @@ def email(self):
1819
return (self.name, self.address)
1920

2021

21-
class IETFEntity(object):
22+
class Entity(object):
2223

23-
def __init__(self, name, poc=None, obj=None, cc=None):
24+
def __init__(self, name, obj=None):
2425
self.name = name
25-
self.poc = poc
26-
self.cc = cc
2726
self.obj = obj
2827

2928
def get_poc(self):
@@ -36,17 +35,54 @@ def get_cc(self, person=None):
3635
return [self.cc]
3736
return self.cc
3837

38+
def get_from_cc(self, person=None):
39+
return []
40+
41+
42+
class IETFEntity(Entity):
43+
44+
poc = FakePerson(**IETFCHAIR)
45+
cc = FakePerson(**IESG)
46+
47+
def get_from_cc(self, person):
48+
result = []
49+
if not is_ietfchair(person):
50+
result.append(self.poc)
51+
result.append(self.cc)
52+
return result
53+
54+
55+
class IABEntity(Entity):
56+
chair = FakePerson(**IABCHAIR)
57+
director = FakePerson(**IABEXECUTIVEDIRECTOR)
58+
poc = [chair, director]
59+
cc = FakePerson(**IAB)
60+
61+
def get_from_cc(self, person):
62+
result = []
63+
if not is_iabchair(person):
64+
result.append(self.chair)
65+
result.append(self.cc)
66+
if not is_iab_executive_director(person):
67+
result.append(self.director)
68+
return result
69+
3970

40-
class AreaEntity(IETFEntity):
71+
class AreaEntity(Entity):
4172

4273
def get_poc(self):
4374
return [i.person for i in self.obj.areadirector_set.all()]
4475

4576
def get_cc(self, person=None):
4677
return [FakePerson(**IETFCHAIR)]
4778

79+
def get_from_cc(self, person):
80+
result = [i.person for i in self.obj.areadirector_set.all() if i.person!=person]
81+
result.append(FakePerson(**IETFCHAIR))
82+
return result
83+
4884

49-
class WGEntity(IETFEntity):
85+
class WGEntity(Entity):
5086

5187
def get_poc(self):
5288
return [i.person for i in self.obj.wgchair_set.all()]
@@ -58,13 +94,24 @@ def get_cc(self, person=None):
5894
address = self.obj.email_address))
5995
return result
6096

97+
def get_from_cc(self, person):
98+
result = [i.person for i in self.obj.wgchair_set.all() if i.person!=person]
99+
result += [i.person for i in self.obj.area_directors()]
100+
if self.obj.email_address:
101+
result.append(FakePerson(name ='%s Discussion List' % self.obj.group_acronym.name,
102+
address = self.obj.email_address))
103+
return result
61104

62-
class SDOEntity(IETFEntity):
105+
106+
class SDOEntity(Entity):
63107

64108
def get_poc(self):
65109
return []
66110

67111
def get_cc(self, person=None):
112+
manager = self.obj.liaisonmanager()
113+
if manager:
114+
return [manager.person]
68115
return []
69116

70117
def get_from_cc(self, person=None):
@@ -74,31 +121,65 @@ def get_from_cc(self, person=None):
74121
return []
75122

76123

77-
class IETFEntityManager(object):
124+
class EntityManager(object):
78125

79-
def __init__(self, pk=None, name=None, queryset=None, poc=None, cc=None):
126+
def __init__(self, pk=None, name=None, queryset=None):
80127
self.pk = pk
81128
self.name = name
82129
self.queryset = queryset
83-
self.poc = poc
84-
self.cc = cc
85130

86131
def get_entity(self, pk=None):
87-
return IETFEntity(name=self.name, poc=self.poc, cc=self.cc)
132+
return Entity(name=self.name, poc=self.poc, cc=self.cc)
88133

89134
def get_managed_list(self):
90135
return [(self.pk, self.name)]
91136

137+
def can_send_on_behalf(self, person):
138+
return []
139+
92140

93-
class AreaEntityManager(IETFEntityManager):
141+
class IETFEntityManager(EntityManager):
94142

95-
def __init__(self, pk=None, name=None, queryset=None, poc=None):
96-
super(AreaEntityManager, self).__init__(pk, name, queryset, poc)
143+
def __init__(self, *args, **kwargs):
144+
super(IETFEntityManager, self).__init__(*args, **kwargs)
145+
self.entity = IETFEntity(name=self.name)
146+
147+
def get_entity(self, pk=None):
148+
return self.entity
149+
150+
def can_send_on_behalf(self, person):
151+
if is_ietfchair(person):
152+
return self.get_managed_list()
153+
return []
154+
155+
156+
class IABEntityManager(EntityManager):
157+
158+
def __init__(self, *args, **kwargs):
159+
super(IABEntityManager, self).__init__(*args, **kwargs)
160+
self.entity = IABEntity(name=self.name)
161+
162+
def get_entity(self, pk=None):
163+
return self.entity
164+
165+
def can_send_on_behalf(self, person):
166+
if (is_iabchair(person) or
167+
is_iab_executive_director(person)):
168+
return self.get_managed_list()
169+
return []
170+
171+
172+
class AreaEntityManager(EntityManager):
173+
174+
def __init__(self, pk=None, name=None, queryset=None):
175+
super(AreaEntityManager, self).__init__(pk, name, queryset)
97176
if self.queryset == None:
98177
self.queryset = Area.active_areas()
99178

100-
def get_managed_list(self):
101-
return [(u'%s_%s' % (self.pk, i.pk), i.area_acronym.name) for i in self.queryset.order_by('area_acronym__name')]
179+
def get_managed_list(self, query_filter=None):
180+
if not query_filter:
181+
query_filter = {}
182+
return [(u'%s_%s' % (self.pk, i.pk), i.area_acronym.name) for i in self.queryset.filter(**query_filter).order_by('area_acronym__name')]
102183

103184
def get_entity(self, pk=None):
104185
if not pk:
@@ -109,16 +190,22 @@ def get_entity(self, pk=None):
109190
return None
110191
return AreaEntity(name=obj.area_acronym.name, obj=obj)
111192

193+
def can_send_on_behalf(self, person):
194+
query_filter = {'areadirector__in': person.areadirector_set.all()}
195+
return self.get_managed_list(query_filter)
112196

113-
class WGEntityManager(IETFEntityManager):
114197

115-
def __init__(self, pk=None, name=None, queryset=None, poc=None):
116-
super(WGEntityManager, self).__init__(pk, name, queryset, poc)
198+
class WGEntityManager(EntityManager):
199+
200+
def __init__(self, pk=None, name=None, queryset=None):
201+
super(WGEntityManager, self).__init__(pk, name, queryset)
117202
if self.queryset == None:
118203
self.queryset = IETFWG.objects.filter(group_type=1, status=IETFWG.ACTIVE, areagroup__area__status=Area.ACTIVE)
119204

120-
def get_managed_list(self):
121-
return [(u'%s_%s' % (self.pk, i.pk), i.group_acronym.name) for i in self.queryset.order_by('group_acronym__name')]
205+
def get_managed_list(self, query_filter=None):
206+
if not query_filter:
207+
query_filter = {}
208+
return [(u'%s_%s' % (self.pk, i.pk), i.group_acronym.name) for i in self.queryset.filter(**query_filter).order_by('group_acronym__name')]
122209

123210
def get_entity(self, pk=None):
124211
if not pk:
@@ -129,11 +216,17 @@ def get_entity(self, pk=None):
129216
return None
130217
return WGEntity(name=obj.group_acronym.name, obj=obj)
131218

219+
def can_send_on_behalf(self, person):
220+
wgs = set([i.group_acronym.pk for i in person.wgchair_set.all()])
221+
wgs = wgs.union([i.group_acronym.pk for i in person.wgsecretary_set.all()])
222+
query_filter = {'pk__in': wgs}
223+
return self.get_managed_list(query_filter)
224+
132225

133-
class SDOEntityManager(IETFEntityManager):
226+
class SDOEntityManager(EntityManager):
134227

135-
def __init__(self, pk=None, name=None, queryset=None, poc=None):
136-
super(SDOEntityManager, self).__init__(pk, name, queryset, poc)
228+
def __init__(self, pk=None, name=None, queryset=None):
229+
super(SDOEntityManager, self).__init__(pk, name, queryset)
137230
if self.queryset == None:
138231
self.queryset = SDOs.objects.all()
139232

@@ -153,16 +246,9 @@ def get_entity(self, pk=None):
153246
class IETFHierarchyManager(object):
154247

155248
def __init__(self):
156-
self.managers = {'ietf': IETFEntityManager(pk='ietf', name=u'The IETF',
157-
poc=FakePerson(**IETFCHAIR),
158-
cc=FakePerson(**IESG)),
159-
'iesg': IETFEntityManager(pk='iesg', name=u'The IESG',
160-
poc=FakePerson(**IETFCHAIR),
161-
cc=FakePerson(**IESG)),
162-
'iab': IETFEntityManager(pk='iab', name=u'The IAB',
163-
poc=[FakePerson(**IABCHAIR),
164-
FakePerson(**IABEXECUTIVEDIRECTOR)],
165-
cc=FakePerson(**IAB)),
249+
self.managers = {'ietf': IETFEntityManager(pk='ietf', name=u'The IETF'),
250+
'iesg': IETFEntityManager(pk='iesg', name=u'The IESG'),
251+
'iab': IABEntityManager(pk='iab', name=u'The IAB'),
166252
'area': AreaEntityManager(pk='area', name=u'IETF Areas'),
167253
'wg': WGEntityManager(pk='wg', name=u'IETF Working Groups'),
168254
'sdo': SDOEntityManager(pk='sdo', name=u'Standards Development Organizations'),
@@ -195,7 +281,22 @@ def get_all_incoming_entities(self):
195281
return entities
196282

197283
def get_all_outgoing_entities(self):
198-
entities = [(self.manager['sdo'].name, self.managers['sdo'].get_managed_list())]
284+
entities = [(self.managers['sdo'].name, self.managers['sdo'].get_managed_list())]
285+
return entities
286+
287+
def get_entities_for_person(self, person):
288+
entities = []
289+
results = []
290+
for key in ['ietf', 'iesg', 'iab']:
291+
results += self.managers[key].can_send_on_behalf(person)
292+
if results:
293+
entities.append(('Main IETF Entities', results))
294+
areas = self.managers['area'].can_send_on_behalf(person)
295+
if areas:
296+
entities.append(('IETF Areas', areas))
297+
wgs = self.managers['wg'].can_send_on_behalf(person)
298+
if wgs:
299+
entities.append(('IETF Working Groups', wgs))
199300
return entities
200301

201302
IETFHM = IETFHierarchyManager()

ietf/liaisons/views.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,8 @@ def get_poc_for_incoming(request):
4848
@can_submit_liaison
4949
def get_cc_for_incoming(request):
5050
entity_id = request.GET.get('to_entity_id', None)
51-
sdo_id = request.GET.get('sdo_id', None)
52-
if not entity_id and not sdo_id:
51+
from_entity_id = request.GET.get('from_entity_id', None)
52+
if not entity_id and not from_entity_id:
5353
result = {'cc': [], 'error': 'No entity id and no sdo id'}
5454
person = get_person_for_user(request.user)
5555
if entity_id:
@@ -58,8 +58,8 @@ def get_cc_for_incoming(request):
5858
result = {'cc': [], 'error': 'Invalid entity id'}
5959
else:
6060
result = {'error': False, 'cc': [i.email() for i in entity.get_cc()]}
61-
if sdo_id:
62-
from_entity = IETFHM.get_entity_by_key(sdo_id)
61+
if from_entity_id:
62+
from_entity = IETFHM.get_entity_by_key(from_entity_id)
6363
result['cc'] += [i.email() for i in from_entity.get_from_cc(person=person)]
6464
json_result = simplejson.dumps(result)
6565
return HttpResponse(json_result, mimetype='text/javascript')

ietf/liaisons/widgets.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ class FromWidget(Select):
66

77
def render(self, name, value, attrs=None, choices=()):
88
all_choices = list(self.choices) + list(choices)
9-
if len(all_choices)!=1:
9+
if len(all_choices)!=1 or \
10+
(isinstance(all_choices[0], (list, tuple)) and \
11+
len(all_choices[0][1])!=1):
1012
base = super(FromWidget, self).render(name, value, attrs, choices)
1113
else:
1214
base = u'<input type="hidden" value="%s" />%s' % all_choices[0]

static/js/liaisons.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@
166166
async: true,
167167
dataType: 'json',
168168
data: {to_entity_id: organization.val(),
169-
sdo_id: sdo.val()},
169+
from_entity_id: sdo.val()},
170170
success: function(response){
171171
if (!response.error) {
172172
render_mails_into(cc, response.cc);

0 commit comments

Comments
 (0)