From 2c92aa213d5c7d47dff953c0cf532ef7b7b81b4d Mon Sep 17 00:00:00 2001 From: Robert Sparks Date: Tue, 11 Jul 2017 19:12:21 +0000 Subject: [PATCH] Treat Area Groups similar to Working Groups and Research Groups where it makes sense to do so. Commit ready for merge. - Legacy-Id: 13832 --- ietf/community/forms.py | 2 +- ietf/community/utils.py | 2 +- ietf/doc/utils.py | 2 +- ietf/group/features.py | 1 + ietf/group/forms.py | 1 + ietf/group/models.py | 4 ++-- ietf/group/tests_info.py | 2 +- ietf/group/utils.py | 4 ++-- ietf/group/views.py | 2 +- ietf/mailinglists/views.py | 2 +- ietf/mailtrigger/models.py | 6 +++--- ietf/mailtrigger/utils.py | 2 +- ietf/meeting/forms.py | 1 + ietf/meeting/views.py | 2 +- ietf/secr/groups/forms.py | 1 + ietf/secr/meetings/views.py | 1 + ietf/secr/proceedings/views.py | 1 + ietf/utils/management/commands/create_group_wikis.py | 2 +- ietf/utils/tests.py | 2 +- 19 files changed, 23 insertions(+), 17 deletions(-) diff --git a/ietf/community/forms.py b/ietf/community/forms.py index 4275bf1fb..d764d2307 100644 --- a/ietf/community/forms.py +++ b/ietf/community/forms.py @@ -39,7 +39,7 @@ class SearchRuleForm(forms.ModelForm): self.fields["group"].label = "Area" self.fields["group"].queryset = self.fields["group"].queryset.filter(Q(type="area") | Q(acronym="irtf")).order_by("acronym") else: - self.fields["group"].queryset = self.fields["group"].queryset.filter(type__in=("wg", "rg")).order_by("acronym") + self.fields["group"].queryset = self.fields["group"].queryset.filter(type__in=("wg", "rg", "ag", )).order_by("acronym") del self.fields["person"] del self.fields["text"] diff --git a/ietf/community/utils.py b/ietf/community/utils.py index 0a573c195..697a09c65 100644 --- a/ietf/community/utils.py +++ b/ietf/community/utils.py @@ -47,7 +47,7 @@ def can_manage_community_list(user, clist): if clist.group.type_id == 'area': return Role.objects.filter(name__slug='ad', person__user=user, group=clist.group).exists() - elif clist.group.type_id in ('wg', 'rg'): + elif clist.group.type_id in ('wg', 'rg', 'ag'): return Role.objects.filter(name__slug='chair', person__user=user, group=clist.group).exists() elif clist.group.type_id in ('program'): return Role.objects.filter(name__slug='lead', person__user=user, group=clist.group).exists() diff --git a/ietf/doc/utils.py b/ietf/doc/utils.py index 4ccc1c2e7..209363da7 100644 --- a/ietf/doc/utils.py +++ b/ietf/doc/utils.py @@ -107,7 +107,7 @@ def can_adopt_draft(user, doc): and doc.group.type_id == "individ") roles = Role.objects.filter(name__in=("chair", "delegate", "secr"), - group__type__in=("wg", "rg"), + group__type__in=("wg", "rg", "ag", ), group__state="active", person__user=user) role_groups = [ r.group for r in roles ] diff --git a/ietf/group/features.py b/ietf/group/features.py index 86a8b8993..1c0700419 100644 --- a/ietf/group/features.py +++ b/ietf/group/features.py @@ -16,6 +16,7 @@ class GroupFeatures(object): admin_roles = ["chair"] def __init__(self, group): + # TODO: should 'ag' be in this list if group.type_id in ("wg", "rg"): self.has_milestones = True self.has_chartering_process = True diff --git a/ietf/group/forms.py b/ietf/group/forms.py index 0d93d6346..83e9a680b 100644 --- a/ietf/group/forms.py +++ b/ietf/group/forms.py @@ -155,6 +155,7 @@ class GroupForm(forms.Form): if existing: raise forms.ValidationError("Acronym used for an existing group (%s)." % existing.name) + # TODO: Why is this limited to types wg and rg? We would want to be warned about _any_ old collision I think? old = GroupHistory.objects.filter(acronym__iexact=acronym, type__in=("wg", "rg")) if old: insert_confirm_field(label="Confirm reusing acronym %s" % old[0].acronym, initial=False) diff --git a/ietf/group/models.py b/ietf/group/models.py index d81a9c2e7..149845bab 100644 --- a/ietf/group/models.py +++ b/ietf/group/models.py @@ -37,7 +37,7 @@ class GroupInfo(models.Model): def name_with_acronym(self): res = self.name - if self.type_id in ("wg", "rg", "area"): + if self.type_id in ("wg", "rg", "ag", "area"): res += " %s (%s)" % (self.type, self.acronym) return res @@ -55,7 +55,7 @@ class GroupInfo(models.Model): # bridge gap between group-type prefixed URLs and /group/ ones from django.urls import reverse as urlreverse kwargs = { 'acronym': self.acronym } - if self.type_id in ("wg", "rg"): + if self.type_id in ("wg", "rg", "ag"): kwargs["group_type"] = self.type_id return urlreverse(self.features.about_page, kwargs=kwargs) diff --git a/ietf/group/tests_info.py b/ietf/group/tests_info.py index 8e02f9530..a6aa87223 100644 --- a/ietf/group/tests_info.py +++ b/ietf/group/tests_info.py @@ -1218,7 +1218,7 @@ class StatusUpdateTests(TestCase): self.assertEqual(response.status_code, 404) self.client.logout() - for type_id in GroupTypeName.objects.exclude(slug__in=('wg','rg','team')).values_list('slug',flat=True): + for type_id in GroupTypeName.objects.exclude(slug__in=('wg','rg','ag','team')).values_list('slug',flat=True): group = GroupFactory.create(type_id=type_id) for user in (None,User.objects.get(username='secretary')): ensure_updates_dont_show(group,user) diff --git a/ietf/group/utils.py b/ietf/group/utils.py index b069c1c41..44619fffb 100644 --- a/ietf/group/utils.py +++ b/ietf/group/utils.py @@ -124,7 +124,7 @@ def can_manage_materials(user, group): return has_role(user, 'Secretariat') or group.has_role(user, ("chair", "delegate", "secr", "matman")) def can_provide_status_update(user, group): - if not group.type_id in ['wg','rg','team']: + if not group.type_id in ['wg','rg','ag','team']: return False return has_role(user, 'Secretariat') or group.has_role(user, ("chair", "delegate", "secr", "ad",)) @@ -181,7 +181,7 @@ def construct_group_menu_context(request, group, selected, group_type, others): import ietf.group.views entries.append(("Review requests", urlreverse(ietf.group.views.review_requests, kwargs=kwargs))) entries.append(("Reviewers", urlreverse(ietf.group.views.reviewer_overview, kwargs=kwargs))) - if group.type_id in ('rg','wg','team'): + if group.type_id in ('rg','wg','ag','team'): entries.append(("Meetings", urlreverse("ietf.group.views.meetings", kwargs=kwargs))) entries.append(("History", urlreverse("ietf.group.views.history", kwargs=kwargs))) entries.append(("Photos", urlreverse("ietf.group.views.group_photos", kwargs=kwargs))) diff --git a/ietf/group/views.py b/ietf/group/views.py index cecdd58f3..296d596a4 100644 --- a/ietf/group/views.py +++ b/ietf/group/views.py @@ -767,7 +767,7 @@ def group_photos(request, group_type=None, acronym=None): group = get_object_or_404(Group, acronym=acronym) roles = sorted(Role.objects.filter(group__acronym=acronym),key=lambda x: x.name.name+x.person.last_name()) - if group.type_id in ['wg', 'rg', ]: + if group.type_id in ['wg', 'rg', 'ag', ]: roles = reorder_roles(roles, ['chair', 'secr']) elif group.type_id in ['nomcom', ]: roles = reorder_roles(roles, ['chair', 'member', 'advisor', ]) diff --git a/ietf/mailinglists/views.py b/ietf/mailinglists/views.py index 391e56fc7..5702bc6da 100644 --- a/ietf/mailinglists/views.py +++ b/ietf/mailinglists/views.py @@ -4,7 +4,7 @@ from ietf.group.models import Group from django.shortcuts import render def groups(request): - groups = Group.objects.filter(type__in=("wg", "rg"), list_archive__startswith='http').order_by("acronym") + groups = Group.objects.filter(type__in=("wg", "rg", "ag"), list_archive__startswith='http').order_by("acronym") return render(request, "mailinglists/group_archives.html", { "groups": groups } ) diff --git a/ietf/mailtrigger/models.py b/ietf/mailtrigger/models.py index b5de7e005..006db903d 100644 --- a/ietf/mailtrigger/models.py +++ b/ietf/mailtrigger/models.py @@ -60,7 +60,7 @@ class Recipient(models.Model): addrs = [] if 'doc' in kwargs: doc=kwargs['doc'] - if doc.group and doc.group.type.slug in ['wg','rg']: + if doc.group and doc.group.type.slug in ['wg','rg','ag',]: addrs.append('%s-chairs@ietf.org'%doc.group.acronym) return addrs @@ -68,7 +68,7 @@ class Recipient(models.Model): addrs = [] if 'doc' in kwargs: doc=kwargs['doc'] - if doc.group and doc.group.type.slug in ['wg','rg']: + if doc.group and doc.group.type.slug in ['wg','rg','ag',]: addrs.extend(doc.group.role_set.filter(name='delegate').values_list('email__address',flat=True)) return addrs @@ -76,7 +76,7 @@ class Recipient(models.Model): addrs = [] if 'doc' in kwargs: doc=kwargs['doc'] - if doc.group.type.slug in ['wg','rg']: + if doc.group.type.slug in ['wg','rg','ag',]: if doc.group.list_email: addrs.append(doc.group.list_email) return addrs diff --git a/ietf/mailtrigger/utils.py b/ietf/mailtrigger/utils.py index 19773b193..14a2c3d1a 100644 --- a/ietf/mailtrigger/utils.py +++ b/ietf/mailtrigger/utils.py @@ -67,7 +67,7 @@ def gather_relevant_expansions(**kwargs): relevant.update(starts_with('group_')) relevant.update(starts_with('milestones_')) group = kwargs['group'] - if group.type_id in ['rg','wg',]: + if group.type_id in ['rg','wg','ag',]: relevant.update(starts_with('session_')) if group.type_id in ['wg',]: relevant.update(['charter_external_review',]) diff --git a/ietf/meeting/forms.py b/ietf/meeting/forms.py index e957d1573..1814e67cb 100644 --- a/ietf/meeting/forms.py +++ b/ietf/meeting/forms.py @@ -92,6 +92,7 @@ class InterimSessionInlineFormSet(BaseInlineFormSet): return # formset doesn't have cleaned_data class InterimMeetingModelForm(forms.ModelForm): + # TODO: Should area groups get to schedule Interims? group = GroupModelChoiceField(queryset=Group.objects.filter(type__in=('wg', 'rg'), state__in=('active', 'proposed', 'bof')).order_by('acronym'), required=False) in_person = forms.BooleanField(required=False) meeting_type = forms.ChoiceField(choices=( diff --git a/ietf/meeting/views.py b/ietf/meeting/views.py index 700b2a6b5..dd023685a 100644 --- a/ietf/meeting/views.py +++ b/ietf/meeting/views.py @@ -1017,7 +1017,7 @@ def meeting_requests(request, num=None): meeting = get_meeting(num) sessions = Session.objects.filter(meeting__number=meeting.number, type__slug='session', group__parent__isnull = False).exclude(requested_by=0).order_by("group__parent__acronym","status__slug","group__acronym") - groups_not_meeting = Group.objects.filter(state='Active',type__in=['WG','RG','BOF']).exclude(acronym__in = [session.group.acronym for session in sessions]).order_by("parent__acronym","acronym") + groups_not_meeting = Group.objects.filter(state='Active',type__in=['wg','rg','ag','bof']).exclude(acronym__in = [session.group.acronym for session in sessions]).order_by("parent__acronym","acronym") return render(request, "meeting/requests.html", {"meeting": meeting, "sessions":sessions, diff --git a/ietf/secr/groups/forms.py b/ietf/secr/groups/forms.py index 46b4b8572..0d1d72cb5 100644 --- a/ietf/secr/groups/forms.py +++ b/ietf/secr/groups/forms.py @@ -153,6 +153,7 @@ class RoleForm(forms.Form): self.group = kwargs.pop('group') super(RoleForm, self).__init__(*args,**kwargs) # this form is re-used in roles app, use different roles in select + # TODO: should 'ag' be excluded here as well? if self.group.type.slug not in ('wg','rg'): self.fields['name'].queryset = RoleName.objects.all() diff --git a/ietf/secr/meetings/views.py b/ietf/secr/meetings/views.py index 4b6050d34..0023cd39f 100644 --- a/ietf/secr/meetings/views.py +++ b/ietf/secr/meetings/views.py @@ -370,6 +370,7 @@ def blue_sheet_generate(request, meeting_id): meeting = get_object_or_404(Meeting, number=meeting_id) if request.method == "POST": + # TODO: Why aren't 'ag' in here as well? groups = Group.objects.filter( type__in=['wg','rg'], session__timeslotassignments__schedule=meeting.agenda).order_by('acronym') diff --git a/ietf/secr/proceedings/views.py b/ietf/secr/proceedings/views.py index a83f5ddd3..299a4b03f 100644 --- a/ietf/secr/proceedings/views.py +++ b/ietf/secr/proceedings/views.py @@ -105,6 +105,7 @@ def get_next_slide_num(session): if slides: # we need this special case for non wg/rg sessions because the name format is different # it should be changed to match the rest + # TODO - why isn't 'ag' in this list (also, is this function still used?) if session.group.type.slug not in ('wg','rg'): nums = [ s.name.split('-')[3] for s in slides ] else: diff --git a/ietf/utils/management/commands/create_group_wikis.py b/ietf/utils/management/commands/create_group_wikis.py index ae01f431f..fc701d65a 100644 --- a/ietf/utils/management/commands/create_group_wikis.py +++ b/ietf/utils/management/commands/create_group_wikis.py @@ -175,7 +175,7 @@ class Command(BaseCommand): self.maybe_add_group_url(group, 'Issue tracker', settings.TRAC_ISSUE_URL_PATTERN % group.acronym) # Use custom assets (if any) from the master setup self.symlink_to_master_assets(group, env) - if group.type_id in ['wg', 'rg', ]: + if group.type_id in ['wg', 'rg', 'ag', ]: self.add_wg_draft_states(group, env) self.add_custom_wiki_pages(group, env) self.add_default_wiki_pages(group, env) diff --git a/ietf/utils/tests.py b/ietf/utils/tests.py index f8d41ea4c..63618afec 100644 --- a/ietf/utils/tests.py +++ b/ietf/utils/tests.py @@ -235,7 +235,7 @@ class TestWikiGlueManagementCommand(TestCase): def test_wiki_create_output(self): make_test_data() groups = Group.objects.filter( - type__slug__in=['wg','rg','area'], + type__slug__in=['wg','rg','ag','area'], state__slug='active' ).order_by('acronym') out = StringIO()