From 847f37dbf7f35ceb22e5bcb8c804e5513cc6c1c6 Mon Sep 17 00:00:00 2001 From: Robert Sparks Date: Tue, 31 Aug 2021 22:13:38 +0000 Subject: [PATCH] Add IETF Administrative LLC groups. Fixes #3302. Commit ready for merge. - Legacy-Id: 19310 --- ietf/doc/templatetags/wg_menu.py | 6 +- .../0046_grouptypename_admin_to_adm.py | 55 +++++++++++ ietf/group/migrations/0047_ietfllc.py | 88 ++++++++++++++++++ ietf/group/tests_info.py | 4 +- ietf/group/views.py | 8 +- ietf/name/fixtures/names.json | 92 ++++++++++++++++--- ietf/templates/group/active_adm.html | 39 ++++++++ ietf/templates/group/active_iabgroups.html | 2 +- ietf/urls.py | 2 +- 9 files changed, 278 insertions(+), 18 deletions(-) create mode 100644 ietf/group/migrations/0046_grouptypename_admin_to_adm.py create mode 100644 ietf/group/migrations/0047_ietfllc.py create mode 100644 ietf/templates/group/active_adm.html diff --git a/ietf/doc/templatetags/wg_menu.py b/ietf/doc/templatetags/wg_menu.py index 89b33c97c..742e0479e 100644 --- a/ietf/doc/templatetags/wg_menu.py +++ b/ietf/doc/templatetags/wg_menu.py @@ -45,9 +45,9 @@ parent_short_names = { } parents = Group.objects.filter( - models.Q(type="area") | models.Q(type="irtf", acronym="irtf") | models.Q(acronym='iab'), + models.Q(type="area") | models.Q(type="irtf", acronym="irtf") | models.Q(acronym='iab') | models.Q(acronym='ietfadminllc'), state="active" - ).order_by('type_id', 'acronym') + ).order_by('type__order','type_id', 'acronym') @register.simple_tag def wg_menu(): @@ -64,5 +64,7 @@ def wg_menu(): p.menu_url = "/rg/" elif p.acronym == "iab": p.menu_url = "/program/" + elif p.acronym == 'ietfadminllc': + p.menu_url = "/adm/" return render_to_string('base/menu_wg.html', { 'parents': parents }) diff --git a/ietf/group/migrations/0046_grouptypename_admin_to_adm.py b/ietf/group/migrations/0046_grouptypename_admin_to_adm.py new file mode 100644 index 000000000..73c268993 --- /dev/null +++ b/ietf/group/migrations/0046_grouptypename_admin_to_adm.py @@ -0,0 +1,55 @@ +# Copyright The IETF Trust 2021 All Rights Reserved + +from django.db import migrations + +def forward(apps, schema_editor): + GroupTypeName = apps.get_model('name','GroupTypeName') + Group = apps.get_model('group', 'Group') + GroupHistory = apps.get_model('group', 'GroupHistory') + GroupFeatures = apps.get_model('group', 'GroupFeatures') + + a = GroupTypeName.objects.get(pk='admin') + a.pk='adm' + a.order=1 + a.save() + f = GroupFeatures.objects.get(pk='admin') + f.pk='adm' + f.save() + + Group.objects.filter(type_id='admin').update(type_id='adm') + GroupHistory.objects.filter(type_id='admin').update(type_id='adm') + + GroupFeatures.objects.filter(pk='admin').delete() + GroupTypeName.objects.filter(pk='admin').delete() + +def reverse(apps, schema_editor): + GroupTypeName = apps.get_model('name','GroupTypeName') + Group = apps.get_model('group', 'Group') + GroupHistory = apps.get_model('group','GroupHistory') + GroupFeatures = apps.get_model('group', 'GroupFeatures') + + a = GroupTypeName.objects.get(pk='adm') + a.pk='admin' + a.order=0 + a.save() + f = GroupFeatures.objects.get(pk='adm') + f.pk='admin' + f.save() + + Group.objects.filter(type_id='adm').update(type_id='admin') + GroupHistory.objects.filter(type_id='adm').update(type_id='admin') + + GroupFeatures.objects.filter(type_id='adm').delete() + GroupTypeName.objects.filter(pk='adm').delete() + + +class Migration(migrations.Migration): + + dependencies = [ + ('group', '0045_iabasg'), + ('name', '0028_iabasg'), + ] + + operations = [ + migrations.RunPython(forward,reverse) + ] diff --git a/ietf/group/migrations/0047_ietfllc.py b/ietf/group/migrations/0047_ietfllc.py new file mode 100644 index 000000000..a946e2bf0 --- /dev/null +++ b/ietf/group/migrations/0047_ietfllc.py @@ -0,0 +1,88 @@ +# Copyright The IETF Trust 2021 All Rights Reserved + +from django.db import migrations + +def email(person): + e = person.email_set.filter(primary=True).first() + if not e: + e = person.email_set.filter(active=True).order_by("-time").first() + return e + +def forward(apps, schema_editor): + Group = apps.get_model('group', 'Group') + Person = apps.get_model('person', 'Person') + llc = Group.objects.create( + acronym='ietfadminllc', + name="IETF Administration LLC", + state_id='active', + type_id='adm', + description="The IETF Administration LLC (IETF LLC) provides the corporate legal home for the IETF, the Internet Architecture Board (IAB), and the Internet Research Task Force (IRTF). The Administration (https://www.ietf.org/about/administration/) section of the website has full details of the LLC and is where the various policies and reports produced by the LLC are published.", + ) + Group.objects.filter(acronym='llc-board').update(parent=llc, description="The IETF Administration LLC (IETF LLC) provides the corporate legal home for the IETF, the Internet Architecture Board (IAB), and the Internet Research Task Force (IRTF). The Administration (https://www.ietf.org/about/administration/) section of the website has full details of the LLC and is where the various policies and reports produced by the LLC are published.") + llc_staff= Group.objects.create( + acronym='llc-staff', + name="IETF LLC employees", + state_id='active', + type_id='adm', + parent=llc, + description="The IETF Administration LLC (IETF LLC) provides the corporate legal home for the IETF, the Internet Architecture Board (IAB), and the Internet Research Task Force (IRTF). The Administration (https://www.ietf.org/about/administration/) section of the website has full details of the LLC and is where the various policies and reports produced by the LLC are published.", + ) + legal = Group.objects.create( + acronym='legal-consult', + name="Legal consultation group", + state_id='active', + type_id='adm', + parent=llc, + description="The legal-consult list is a group of community participants who provide their views to the IETF Administration LLC in private on various legal matters. This was first established under the IAOC and has not been reviewed since. Legal advice is provided separately to the LLC by contracted external counsel.", + ) + + for email_addr in ('jay@ietf.org', 'ghwood@ietf.org', 'lbshaw@ietf.org', 'krathnayake@ietf.org'): + p = Person.objects.get(email__address=email_addr) + llc_staff.role_set.create(name_id='member',person=p,email=email(p)) + + for email_addr in ( + 'amorris@amsl.com', + 'brad@biddle.law', + 'David.Wilson@thompsonhine.com', + 'glenn.deen@nbcuni.com', + 'hall@isoc.org', + 'Jason_Livingood@comcast.com', + 'jay@ietf.org', + 'jmh@joelhalpern.com', + 'johnl@taugh.com', + 'kathleen.moriarty.ietf@gmail.com', + 'lars@eggert.org', + 'lflynn@amsl.com', + 'stewe@stewe.org', + 'vigdis@biddle.law', + 'wendy@seltzer.org', + ): + p = Person.objects.filter(email__address=email_addr).first() + if p: + legal.role_set.create(name_id='member', person=p, email=email(p)) + + +def reverse(apps, schema_editor): + Group = apps.get_model('group', 'Group') + Group.objects.filter(acronym='llc-board').update(parent=None) + Group.objects.filter(acronym__in=['llc_staff','legal-consult']).delete() + Group.objects.filter(acronym='ietfadminllc').delete() + + +class Migration(migrations.Migration): + + dependencies = [ + ('group', '0046_grouptypename_admin_to_adm'), + ('person', '0019_auto_20210604_1443'), + # The below are needed for reverse migrations to work + ('name','0028_iabasg'), + ('doc', '0043_bofreq_docevents'), + ('liaisons','0009_delete_liaisonstatementgroupcontacts_model'), + ('meeting', '0018_document_primary_key_cleanup'), + ('review', '0014_document_primary_key_cleanup'), + ('submit', '0008_submissionextresource'), + ] + + operations = [ + migrations.RunPython(forward,reverse) + ] diff --git a/ietf/group/tests_info.py b/ietf/group/tests_info.py index 461cad89c..939be9c9a 100644 --- a/ietf/group/tests_info.py +++ b/ietf/group/tests_info.py @@ -74,7 +74,7 @@ class GroupPagesTests(TestCase): self.assertContains(r, group.name) self.assertContains(r, escape(group.ad_role().person.plain_name())) - for t in ('rg','area','ag', 'rag', 'dir','review','team','program'): + for t in ('rg','area','ag', 'rag', 'dir','review','team','program','iabasg','adm'): g = GroupFactory.create(type_id=t,state_id='active') if t in ['dir','review']: g.parent = GroupFactory.create(type_id='area',state_id='active') @@ -90,7 +90,7 @@ class GroupPagesTests(TestCase): self.assertContains(r, "Directorate") self.assertContains(r, "AG") - for slug in GroupTypeName.objects.exclude(slug__in=['wg','rg','ag','rag','area','dir','review','team','program','adhoc','ise']).values_list('slug',flat=True): + for slug in GroupTypeName.objects.exclude(slug__in=['wg','rg','ag','rag','area','dir','review','team','program','adhoc','ise','adm','iabasg']).values_list('slug',flat=True): with self.assertRaises(NoReverseMatch): url=urlreverse('ietf.group.views.active_groups', kwargs=dict(group_type=slug)) diff --git a/ietf/group/views.py b/ietf/group/views.py index a1c873c45..a9552e85a 100644 --- a/ietf/group/views.py +++ b/ietf/group/views.py @@ -294,6 +294,8 @@ def active_groups(request, group_type=None): return active_review_dirs(request) elif group_type in ("program", "iabasg"): return active_iab(request) + elif group_type == "adm": + return active_adm(request) else: raise Http404 @@ -327,6 +329,10 @@ def active_iab(request): group.leads = sorted(roles(group, "lead"), key=extract_last_name) return render(request, 'group/active_iabgroups.html', {'iabgroups' : iabgroups }) +def active_adm(request): + adm = Group.objects.filter(type="adm", state="active").order_by("parent","name") + return render(request, 'group/active_adm.html', {'adm' : adm }) + def active_areas(request): areas = Group.objects.filter(type="area", state="active").order_by("name") return render(request, 'group/active_areas.html', {'areas': areas }) @@ -1290,7 +1296,7 @@ def group_json(request, acronym): @cache_control(public=True, max_age=30*60) @cache_page(30 * 60) def group_menu_data(request): - groups = Group.objects.filter(state="active", parent__state="active").filter(Q(type__features__acts_like_wg=True)|Q(type_id__in=['program','iabasg'])).order_by("-type_id","acronym") + groups = Group.objects.filter(state="active", parent__state="active").filter(Q(type__features__acts_like_wg=True)|Q(type_id__in=['program','iabasg'])|Q(parent__acronym='ietfadminllc')).order_by("-type_id","acronym") groups_by_parent = defaultdict(list) for g in groups: diff --git a/ietf/name/fixtures/names.json b/ietf/name/fixtures/names.json index 5f2700677..86ee36a56 100644 --- a/ietf/name/fixtures/names.json +++ b/ietf/name/fixtures/names.json @@ -2620,7 +2620,7 @@ "show_on_agenda": false }, "model": "group.groupfeatures", - "pk": "admin" + "pk": "adm" }, { "fields": { @@ -2771,6 +2771,43 @@ "model": "group.groupfeatures", "pk": "iab" }, + { + "fields": { + "about_page": "ietf.group.views.group_about", + "acts_like_wg": false, + "admin_roles": "[\n \"lead\"\n]", + "agenda_type": "ad", + "create_wiki": false, + "custom_group_roles": true, + "customize_workflow": false, + "default_parent": "", + "default_tab": "ietf.group.views.group_about", + "default_used_roles": "[\n \"member\",\n \"chair\",\n \"lead\"\n]", + "docman_roles": "[\n \"lead\",\n \"chair\",\n \"secr\"\n]", + "groupman_authroles": "[\n \"Secretariat\",\n \"IAB\"\n]", + "groupman_roles": "[\n \"lead\",\n \"chair\",\n \"secr\"\n]", + "has_chartering_process": false, + "has_default_jabber": false, + "has_documents": true, + "has_meetings": true, + "has_milestones": true, + "has_nonsession_materials": false, + "has_reviews": false, + "has_session_materials": false, + "is_schedulable": false, + "material_types": "[\n \"slides\"\n]", + "matman_roles": "[\n \"lead\",\n \"chair\",\n \"secr\"\n]", + "need_parent": false, + "parent_types": [ + "ietf" + ], + "req_subm_approval": false, + "role_order": "[\n \"lead\",\n \"chair\",\n \"secr\"\n]", + "show_on_agenda": false + }, + "model": "group.groupfeatures", + "pk": "iabasg" + }, { "fields": { "about_page": "ietf.group.views.group_about", @@ -3295,7 +3332,7 @@ "default_tab": "ietf.group.views.group_about", "default_used_roles": "[\n \"ad\",\n \"member\",\n \"delegate\",\n \"secr\",\n \"liaison\",\n \"atlarge\",\n \"chair\",\n \"matman\",\n \"techadv\"\n]", "docman_roles": "[\n \"chair\"\n]", - "groupman_authroles": "[\n \"Secretariat\"\n]", + "groupman_authroles": "[\n \"Secretariat\",\n \"Area Director\"\n]", "groupman_roles": "[\n \"chair\"\n]", "has_chartering_process": false, "has_default_jabber": false, @@ -10719,12 +10756,12 @@ "fields": { "desc": "", "name": "Admin", - "order": 0, + "order": 1, "used": true, "verbose_name": "Administrative Group" }, "model": "name.grouptypename", - "pk": "admin" + "pk": "adm" }, { "fields": { @@ -10770,6 +10807,17 @@ "model": "name.grouptypename", "pk": "iab" }, + { + "fields": { + "desc": "", + "name": "IAB ASG", + "order": 0, + "used": true, + "verbose_name": "IAB Administrative Support Group" + }, + "model": "name.grouptypename", + "pk": "iabasg" + }, { "fields": { "desc": "", @@ -10971,14 +11019,36 @@ { "fields": { "default_offset_days": -57, - "desc": "Preliminary BOF proposals requested. To request a BOF, please see instructions on requesting a BOF at https://www.ietf.org/how/bofs/bof-procedures/", - "name": "Preliminary BOF proposals requested", + "desc": "Cut-off date for BOF proposal requests. To request a BOF, please see instructions at https://www.ietf.org/how/bofs/bof-procedures on Requesting a BOF", + "name": "Cut-off preliminary BOF requests", "order": 0, "used": true }, "model": "name.importantdatename", + "pk": "bofprelimcutoff" + }, + { + "fields": { + "default_offset_days": -57, + "desc": "Preliminary BOF proposals requested. To request a BOF, please see instructions on requesting a BOF at https://www.ietf.org/how/bofs/bof-procedures/", + "name": "Preliminary BOF proposals requested", + "order": 0, + "used": false + }, + "model": "name.importantdatename", "pk": "bofproposals" }, + { + "fields": { + "default_offset_days": -43, + "desc": "Cut-off date for revised BOF proposal requests to Area Directors at UTC 23:59. To request a BOF, please see instructions at https://www.ietf.org/how/bofs/bof-procedures on Requesting a BOF.", + "name": "Cut-off revised BOF requests", + "order": 0, + "used": true + }, + "model": "name.importantdatename", + "pk": "bofrevcutoff" + }, { "fields": { "default_offset_days": -36, @@ -10996,7 +11066,7 @@ "desc": "Cut-off date for BOF proposal requests to Area Directors at UTC 23:59", "name": "Cut-off BOF scheduling Requests", "order": 0, - "used": true + "used": false }, "model": "name.importantdatename", "pk": "cutoffbofreq" @@ -15485,7 +15555,7 @@ "fields": { "command": "xym", "switch": "--version", - "time": "2021-07-13T00:12:25.184", + "time": "2021-08-30T00:16:41.046", "used": true, "version": "xym 0.5" }, @@ -15496,7 +15566,7 @@ "fields": { "command": "pyang", "switch": "--version", - "time": "2021-07-13T00:12:26.721", + "time": "2021-08-30T00:16:42.619", "used": true, "version": "pyang 2.5.0" }, @@ -15507,7 +15577,7 @@ "fields": { "command": "yanglint", "switch": "--version", - "time": "2021-07-13T00:12:27.015", + "time": "2021-08-30T00:16:42.981", "used": true, "version": "yanglint SO 1.6.7" }, @@ -15518,7 +15588,7 @@ "fields": { "command": "xml2rfc", "switch": "--version", - "time": "2021-07-13T00:12:29.814", + "time": "2021-08-30T00:16:45.742", "used": true, "version": "xml2rfc 3.9.1" }, diff --git a/ietf/templates/group/active_adm.html b/ietf/templates/group/active_adm.html new file mode 100644 index 000000000..b038312be --- /dev/null +++ b/ietf/templates/group/active_adm.html @@ -0,0 +1,39 @@ +{% extends "base.html" %} +{# Copyright The IETF Trust 2021, All Rights Reserved #} +{% load origin static %} + +{% block pagehead %} + +{% endblock %} + +{% block title %}Active administrative groups{% endblock %} + + +{% block content %} + {% origin %} + {% regroup adm by parent as grouped_groups %} + {% for grouptype in grouped_groups %} +

Active {% firstof grouptype.grouper.verbose_name grouptype.grouper.name 'Top-level Administration' %} Groups

+ + + + + + + + + {% for group in grouptype.list %} + + + + + {% endfor %} + +
{{grouptype.grouper}}Name
{{ group.acronym }}{{ group.name }}
+ {% endfor %} + +{% endblock %} + +{% block js %} + +{% endblock %} diff --git a/ietf/templates/group/active_iabgroups.html b/ietf/templates/group/active_iabgroups.html index d57e35eca..fb662ea2e 100644 --- a/ietf/templates/group/active_iabgroups.html +++ b/ietf/templates/group/active_iabgroups.html @@ -1,5 +1,5 @@ {% extends "base.html" %} -{# Copyright The IETF Trust 2015, All Rights Reserved #} +{# Copyright The IETF Trust 2021, All Rights Reserved #} {% load origin static %} {% block pagehead %} diff --git a/ietf/urls.py b/ietf/urls.py index 6e52b3960..91e3920bc 100644 --- a/ietf/urls.py +++ b/ietf/urls.py @@ -66,7 +66,7 @@ urlpatterns = [ url(r'^submit/', include('ietf.submit.urls')), url(r'^sync/', include('ietf.sync.urls')), url(r'^templates/', include('ietf.dbtemplate.urls')), - url(r'^(?P(wg|rg|ag|rag|team|dir|review|area|program|iabasg|adhoc|ise))/', include(grouptype_urls)), + url(r'^(?P(wg|rg|ag|rag|team|dir|review|area|program|iabasg|adhoc|ise|adm))/', include(grouptype_urls)), # Redirects url(r'^(?Ppublic)/', include('ietf.redirects.urls')),