|
1 | | -# Copyright The IETF Trust 2013-2019, All Rights Reserved |
| 1 | +# Copyright The IETF Trust 2013-2020, All Rights Reserved |
2 | 2 | # -*- coding: utf-8 -*- |
3 | 3 |
|
4 | 4 |
|
|
20 | 20 | NUM_SESSION_CHOICES = (('','--Please select'),('1','1'),('2','2')) |
21 | 21 | # LENGTH_SESSION_CHOICES = (('','--Please select'),('1800','30 minutes'),('3600','1 hour'),('5400','1.5 hours'), ('7200','2 hours'),('9000','2.5 hours')) |
22 | 22 | LENGTH_SESSION_CHOICES = (('','--Please select'),('1800','30 minutes'),('3600','1 hour'),('5400','1.5 hours'), ('7200','2 hours')) |
23 | | -WG_CHOICES = list( Group.objects.filter(type__in=('wg','rg','ag'),state__in=('bof','proposed','active')).values_list('acronym','acronym').order_by('acronym')) # type:ignore |
24 | | -WG_CHOICES.insert(0,('','--Select WG(s)')) # type:ignore |
25 | 23 |
|
26 | 24 | # ------------------------------------------------- |
27 | 25 | # Helper Functions |
28 | 26 | # ------------------------------------------------- |
29 | | -def check_conflict(groups): |
| 27 | +def allowed_conflicting_groups(): |
| 28 | + return Group.objects.filter(type__in=['wg', 'ag', 'rg'], state__in=['bof', 'proposed', 'active']) |
| 29 | + |
| 30 | +def check_conflict(groups, source_group): |
30 | 31 | ''' |
31 | 32 | Takes a string which is a list of group acronyms. Checks that they are all active groups |
32 | 33 | ''' |
33 | 34 | # convert to python list (allow space or comma separated lists) |
34 | 35 | items = groups.replace(',',' ').split() |
35 | | - active_groups = Group.objects.filter(type__in=('wg','ag','rg'), state__in=('bof','proposed','active')) |
| 36 | + active_groups = allowed_conflicting_groups() |
36 | 37 | for group in items: |
| 38 | + if group == source_group.acronym: |
| 39 | + raise forms.ValidationError("Cannot declare a conflict with the same group: %s" % group) |
| 40 | + |
37 | 41 | if not active_groups.filter(acronym=group): |
38 | 42 | raise forms.ValidationError("Invalid or inactive group acronym: %s" % group) |
39 | 43 |
|
@@ -67,28 +71,39 @@ class SessionForm(forms.Form): |
67 | 71 | length_session2 = forms.ChoiceField(choices=LENGTH_SESSION_CHOICES,required=False) |
68 | 72 | length_session3 = forms.ChoiceField(choices=LENGTH_SESSION_CHOICES,required=False) |
69 | 73 | attendees = forms.IntegerField() |
| 74 | + # FIXME: it would cleaner to have these be |
| 75 | + # ModelMultipleChoiceField, and just customize the widgetry, that |
| 76 | + # way validation comes for free |
70 | 77 | conflict1 = forms.CharField(max_length=255,required=False) |
71 | 78 | conflict2 = forms.CharField(max_length=255,required=False) |
72 | 79 | conflict3 = forms.CharField(max_length=255,required=False) |
73 | 80 | comments = forms.CharField(max_length=200,required=False) |
74 | | - wg_selector1 = forms.ChoiceField(choices=WG_CHOICES,required=False) |
75 | | - wg_selector2 = forms.ChoiceField(choices=WG_CHOICES,required=False) |
76 | | - wg_selector3 = forms.ChoiceField(choices=WG_CHOICES,required=False) |
| 81 | + wg_selector1 = forms.ChoiceField(choices=[],required=False) |
| 82 | + wg_selector2 = forms.ChoiceField(choices=[],required=False) |
| 83 | + wg_selector3 = forms.ChoiceField(choices=[],required=False) |
77 | 84 | third_session = forms.BooleanField(required=False) |
78 | 85 | resources = forms.MultipleChoiceField(widget=forms.CheckboxSelectMultiple,required=False) |
79 | 86 | bethere = SearchablePersonsField(label="Must be present", required=False) |
80 | 87 |
|
81 | | - def __init__(self, *args, **kwargs): |
| 88 | + def __init__(self, group, *args, **kwargs): |
82 | 89 | if 'hidden' in kwargs: |
83 | 90 | self.hidden = kwargs.pop('hidden') |
84 | 91 | else: |
85 | 92 | self.hidden = False |
| 93 | + |
| 94 | + self.group = group |
| 95 | + |
86 | 96 | super(SessionForm, self).__init__(*args, **kwargs) |
87 | 97 | self.fields['num_session'].widget.attrs['onChange'] = "stat_ls(this.selectedIndex);" |
88 | 98 | self.fields['length_session1'].widget.attrs['onClick'] = "if (check_num_session(1)) this.disabled=true;" |
89 | 99 | self.fields['length_session2'].widget.attrs['onClick'] = "if (check_num_session(2)) this.disabled=true;" |
90 | 100 | self.fields['length_session3'].widget.attrs['onClick'] = "if (check_third_session()) { this.disabled=true;}" |
91 | 101 | self.fields['comments'].widget = forms.Textarea(attrs={'rows':'6','cols':'65'}) |
| 102 | + |
| 103 | + group_acronym_choices = [('','--Select WG(s)')] + list(allowed_conflicting_groups().exclude(pk=group.pk).values_list('acronym','acronym').order_by('acronym')) |
| 104 | + for i in range(1, 4): |
| 105 | + self.fields['wg_selector{}'.format(i)].choices = group_acronym_choices |
| 106 | + |
92 | 107 | # disabling handleconflictfield (which only enables or disables form elements) while we're hacking the meaning of the three constraints currently in use: |
93 | 108 | #self.fields['wg_selector1'].widget.attrs['onChange'] = "document.form_post.conflict1.value=document.form_post.conflict1.value + ' ' + this.options[this.selectedIndex].value; return handleconflictfield(1);" |
94 | 109 | #self.fields['wg_selector2'].widget.attrs['onChange'] = "document.form_post.conflict2.value=document.form_post.conflict2.value + ' ' + this.options[this.selectedIndex].value; return handleconflictfield(2);" |
@@ -117,17 +132,17 @@ def __init__(self, *args, **kwargs): |
117 | 132 |
|
118 | 133 | def clean_conflict1(self): |
119 | 134 | conflict = self.cleaned_data['conflict1'] |
120 | | - check_conflict(conflict) |
| 135 | + check_conflict(conflict, self.group) |
121 | 136 | return conflict |
122 | 137 |
|
123 | 138 | def clean_conflict2(self): |
124 | 139 | conflict = self.cleaned_data['conflict2'] |
125 | | - check_conflict(conflict) |
| 140 | + check_conflict(conflict, self.group) |
126 | 141 | return conflict |
127 | 142 |
|
128 | 143 | def clean_conflict3(self): |
129 | 144 | conflict = self.cleaned_data['conflict3'] |
130 | | - check_conflict(conflict) |
| 145 | + check_conflict(conflict, self.group) |
131 | 146 | return conflict |
132 | 147 |
|
133 | 148 | def clean(self): |
|
0 commit comments