Merged in an update from trunk@9942.
- Legacy-Id: 9961
This commit is contained in:
commit
11411d2c30
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
import os, sys, re, datetime, argparse, traceback, tempfile, json, subprocess
|
import os, sys, re, datetime, argparse, traceback, tempfile, json, subprocess
|
||||||
import html5lib
|
import html5lib
|
||||||
import debug # pyflakes:ignore
|
|
||||||
import random
|
import random
|
||||||
|
|
||||||
# Set up import path to find our own Django
|
# Set up import path to find our own Django
|
||||||
|
@ -33,6 +32,8 @@ parser.add_argument('--random', action='store_true',
|
||||||
parser.add_argument('--validate-all', dest='validate_all', action='store_true', default=False,
|
parser.add_argument('--validate-all', dest='validate_all', action='store_true', default=False,
|
||||||
help='Run html 5 validation on all pages, without skipping similar urls. '
|
help='Run html 5 validation on all pages, without skipping similar urls. '
|
||||||
'(The default is to only run validation on one of /foo/1/, /foo/2/, /foo/3/, etc.)')
|
'(The default is to only run validation on one of /foo/1/, /foo/2/, /foo/3/, etc.)')
|
||||||
|
parser.add_argument('-v', '--verbose', action='store_true', default=False,
|
||||||
|
help='Be more verbose')
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
@ -44,6 +45,9 @@ import django.test
|
||||||
|
|
||||||
django.setup()
|
django.setup()
|
||||||
|
|
||||||
|
# This needs to come after we set up sys path to include the local django
|
||||||
|
import debug # pyflakes:ignore
|
||||||
|
|
||||||
# prevent memory from leaking when settings.DEBUG=True
|
# prevent memory from leaking when settings.DEBUG=True
|
||||||
from django.db import connection
|
from django.db import connection
|
||||||
class DontSaveQueries(object):
|
class DontSaveQueries(object):
|
||||||
|
@ -59,6 +63,11 @@ MAX_URL_LENGTH = 500
|
||||||
|
|
||||||
# --- Functions ---
|
# --- Functions ---
|
||||||
|
|
||||||
|
def note(s):
|
||||||
|
if args.verbose:
|
||||||
|
sys.stderr.write(s)
|
||||||
|
sys.stderr.write('\n')
|
||||||
|
|
||||||
def strip_url(url):
|
def strip_url(url):
|
||||||
if url.startswith("http://testserver"):
|
if url.startswith("http://testserver"):
|
||||||
url = url[len("http://testserver"):]
|
url = url[len("http://testserver"):]
|
||||||
|
@ -105,26 +114,45 @@ def extract_tastypie_urls(content):
|
||||||
|
|
||||||
def check_html_valid(url, response, args):
|
def check_html_valid(url, response, args):
|
||||||
global parser, validated_urls, doc_types, warnings
|
global parser, validated_urls, doc_types, warnings
|
||||||
# These URLs have known issues, skip them until those are fixed
|
|
||||||
if re.search('(/secr|admin/)|/doc/.*/edit/info/', url):
|
|
||||||
log("%s blacklisted; skipping HTML validation" % url)
|
|
||||||
return
|
|
||||||
key = url
|
key = url
|
||||||
if not args.validate_all:
|
if not args.validate_all:
|
||||||
# derive a key for urls like this by replacing primary keys
|
# derive a key for urls like this by replacing primary keys
|
||||||
key = re.sub("/[0-9.]+/", "/nnnn/", key)
|
|
||||||
key = re.sub("/.+@.+/", "/x@x.org/", key)
|
|
||||||
key = re.sub("#.*$", "", key)
|
|
||||||
key = re.sub("\?.*$", "", key)
|
key = re.sub("\?.*$", "", key)
|
||||||
key = re.sub("/rfc[0-9]+/", "/rfcnnnn/", key)
|
key = re.sub("#.*$", "", key)
|
||||||
key = re.sub("/wg/[a-z0-9-]+/", "/wg/foo/", key)
|
key = re.sub("/.+@.+/", "/x@x.org/", key)
|
||||||
key = re.sub("/rg/[a-z0-9-]+/", "/rg/foo/", key)
|
key = re.sub("/[0-9.]+/", "/nnnn/", key)
|
||||||
key = re.sub("/ipr/[0-9]+/", "/ipr/nnnn/", key)
|
key = re.sub("/[0-9.]+/", "/mmmm/", key)
|
||||||
|
key = re.sub("/ag/[a-z0-9-]+/", "/ag/foo/", key)
|
||||||
|
key = re.sub("/area/[a-z0-9-]+/", "/area/foo/", key)
|
||||||
|
key = re.sub("/bcp[0-9]+/", "/bcpnnn/", key)
|
||||||
|
key = re.sub("/conflict-review-[a-z0-9-]+/", "/conflrev-foo/", key)
|
||||||
|
key = re.sub("/dir/[a-z0-9-]+/", "/dir/foo/", key)
|
||||||
key = re.sub("/draft-[a-z0-9-]+/", "/draft-foo/", key)
|
key = re.sub("/draft-[a-z0-9-]+/", "/draft-foo/", key)
|
||||||
|
key = re.sub("/group/[a-z0-9-]+/", "/group/foo/", key)
|
||||||
|
key = re.sub("/ipr/search/.*", "/ipr/search/", key)
|
||||||
|
key = re.sub("/release/[0-9dev.]+/", "/release/n.n.n/", key)
|
||||||
|
key = re.sub("/rfc[0-9]+/", "/rfcnnnn/", key)
|
||||||
|
key = re.sub("/rg/[a-z0-9-]+/", "/rg/foo/", key)
|
||||||
|
key = re.sub("/secr/srec/nnnn/[0-9a-z-]+/", "/secr/sreq/nn/bar/", key)
|
||||||
|
key = re.sub("/state/[a-z0-9-]+/", "/state/foo/", key)
|
||||||
|
key = re.sub("/state/[a-z0-9-]+/[a-z0-9-]+/", "/state/foo/bar/", key)
|
||||||
|
key = re.sub("/status-change-[a-z0-9-]+/", "/statchg-foo/", key)
|
||||||
|
key = re.sub("/std[0-9]+/", "/stdnnn/", key)
|
||||||
|
key = re.sub("/submit/status/nnnn/[0-9a-f]+/", "/submit/status/nnnn/bar/", key)
|
||||||
|
key = re.sub("/team/[a-z0-9-]+/", "/team/foo/", key)
|
||||||
|
key = re.sub("/wg/[a-z0-9-]+/", "/wg/foo/", key)
|
||||||
|
|
||||||
for slug in doc_types:
|
for slug in doc_types:
|
||||||
key = re.sub("/%s-.*/"%slug, "/%s-nnnn/"%slug, key)
|
key = re.sub("/%s-.*/"%slug, "/%s-nnnn/"%slug, key)
|
||||||
|
|
||||||
if not key in validated_urls:
|
if not key in validated_urls:
|
||||||
|
note('Validate: %-32s: %s' % (url[:32], key))
|
||||||
|
# These URLs have known issues, skip them until those are fixed
|
||||||
|
if re.search('(/secr|admin/)|/doc/.*/edit/info/', url):
|
||||||
|
log("%s blacklisted; skipping HTML validation" % url)
|
||||||
|
validated_urls[key] = True
|
||||||
|
return
|
||||||
|
|
||||||
if hasattr(response, "content"):
|
if hasattr(response, "content"):
|
||||||
content = response.content
|
content = response.content
|
||||||
else:
|
else:
|
||||||
|
@ -156,6 +184,14 @@ def check_html_valid(url, response, args):
|
||||||
(pos, code))
|
(pos, code))
|
||||||
warnings += 1
|
warnings += 1
|
||||||
|
|
||||||
|
def skip_url(url):
|
||||||
|
for pattern in (
|
||||||
|
"^/community/[0-9]+/remove_document/",
|
||||||
|
"^/community/personal/",
|
||||||
|
):
|
||||||
|
if re.search(pattern, url):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
def log(s):
|
def log(s):
|
||||||
print(s)
|
print(s)
|
||||||
|
@ -243,6 +279,9 @@ if __name__ == "__main__":
|
||||||
|
|
||||||
visited.add(url)
|
visited.add(url)
|
||||||
|
|
||||||
|
if skip_url(url):
|
||||||
|
continue
|
||||||
|
|
||||||
try:
|
try:
|
||||||
timestamp = datetime.datetime.now()
|
timestamp = datetime.datetime.now()
|
||||||
r = client.get(url, secure=True, follow=True)
|
r = client.get(url, secure=True, follow=True)
|
||||||
|
@ -298,7 +337,7 @@ if __name__ == "__main__":
|
||||||
log("=============")
|
log("=============")
|
||||||
|
|
||||||
else:
|
else:
|
||||||
tags.append(u"FAIL for %s\n (from %s)" % (url, referrer))
|
tags.append(u"FAIL (from %s)" % (referrer, ))
|
||||||
errors += 1
|
errors += 1
|
||||||
|
|
||||||
if elapsed.total_seconds() > slow_threshold:
|
if elapsed.total_seconds() > slow_threshold:
|
||||||
|
|
37
changelog
37
changelog
|
@ -1,3 +1,40 @@
|
||||||
|
ietfdb (6.3.0) ietf; urgency=medium
|
||||||
|
|
||||||
|
**Active area, directorate, team, and area group pages**
|
||||||
|
|
||||||
|
This release provides new group overview pages for active areas, area
|
||||||
|
groups, teams, and directorates. It also improves the error reporting when
|
||||||
|
drafts are submitted with invalid XML, providing line numbers and specifics
|
||||||
|
for the issues found. Additionally, there are a few bug fixes.
|
||||||
|
|
||||||
|
* Merged in [9924] from rjsparks@nostrum.com:
|
||||||
|
Added views of active areas, area groups, teams, and directorates. Added
|
||||||
|
navigation to those views to the base menus. Unified the URL patterns
|
||||||
|
shared between group/urls and group/urls_info, exposing the same view at,
|
||||||
|
e.g., /group/stir and /wg/stir/. Improved testing, primarily of
|
||||||
|
group/info.py
|
||||||
|
|
||||||
|
* Merged in [9901] from rcross@amsl.com:
|
||||||
|
Fixed matching audio file names with rooms.
|
||||||
|
|
||||||
|
* Provided a document's rfc number (if any) as part of the document fields
|
||||||
|
exposed in the json api.
|
||||||
|
|
||||||
|
* Changed the code for meta-data extraction from xml files to not break
|
||||||
|
if a sought-after element is missing.
|
||||||
|
|
||||||
|
* Updated the meta-data error message to say 'errors ... below' instead of
|
||||||
|
'errors ... above', to match the relative placement of text and error
|
||||||
|
indications.
|
||||||
|
|
||||||
|
* Improved the error reporting for invalid xml file submissions.
|
||||||
|
|
||||||
|
* Improved the handling of failed xml2rfc conversions when no txt document
|
||||||
|
is submitted.
|
||||||
|
|
||||||
|
-- Henrik Levkowetz <henrik@levkowetz.com> 01 Aug 2015 14:52:37 +0000
|
||||||
|
|
||||||
|
|
||||||
ietfdb (6.2.0) ietf; urgency=medium
|
ietfdb (6.2.0) ietf; urgency=medium
|
||||||
|
|
||||||
**XML-Only Draft Submission**
|
**XML-Only Draft Submission**
|
||||||
|
|
|
@ -2,13 +2,13 @@
|
||||||
import checks # pyflakes:ignore
|
import checks # pyflakes:ignore
|
||||||
|
|
||||||
# Don't add patch number here:
|
# Don't add patch number here:
|
||||||
__version__ = "6.2.1.dev0"
|
__version__ = "6.3.1.dev0"
|
||||||
|
|
||||||
# set this to ".p1", ".p2", etc. after patching
|
# set this to ".p1", ".p2", etc. after patching
|
||||||
__patch__ = ""
|
__patch__ = ""
|
||||||
|
|
||||||
__date__ = "$Date$"
|
__date__ = "$Date$"
|
||||||
|
|
||||||
__rev__ = "$Rev$ (dev) Latest release: Rev. 9880 "
|
__rev__ = "$Rev$ (dev) Latest release: Rev. 9940 "
|
||||||
|
|
||||||
__id__ = "$Id$"
|
__id__ = "$Id$"
|
||||||
|
|
|
@ -179,7 +179,7 @@ def generate_approval_mail_approved(request, doc):
|
||||||
doc.group.name_with_wg = doc.group.name + " Working Group"
|
doc.group.name_with_wg = doc.group.name + " Working Group"
|
||||||
if doc.group.list_email:
|
if doc.group.list_email:
|
||||||
cc.append("%s mailing list <%s>" % (doc.group.acronym, doc.group.list_email))
|
cc.append("%s mailing list <%s>" % (doc.group.acronym, doc.group.list_email))
|
||||||
cc.append("%s chair <%s-chairs@tools.ietf.org>" % (doc.group.acronym, doc.group.acronym))
|
cc.append("%s chair <%s-chairs@ietf.org>" % (doc.group.acronym, doc.group.acronym))
|
||||||
else:
|
else:
|
||||||
doc.group.name_with_wg = doc.group.name
|
doc.group.name_with_wg = doc.group.name
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# Autogenerated by the mkresources management command 2014-12-14 19:50
|
# Autogenerated by the mkresources management command 2014-12-14 19:50
|
||||||
from tastypie.resources import ModelResource
|
from tastypie.resources import ModelResource
|
||||||
from tastypie.fields import ToOneField, ToManyField
|
from tastypie.fields import ToOneField, ToManyField, CharField
|
||||||
from tastypie.constants import ALL, ALL_WITH_RELATIONS
|
from tastypie.constants import ALL, ALL_WITH_RELATIONS
|
||||||
|
|
||||||
from ietf import api
|
from ietf import api
|
||||||
|
@ -86,6 +86,7 @@ class DocumentResource(ModelResource):
|
||||||
states = ToManyField(StateResource, 'states', null=True)
|
states = ToManyField(StateResource, 'states', null=True)
|
||||||
tags = ToManyField(DocTagNameResource, 'tags', null=True)
|
tags = ToManyField(DocTagNameResource, 'tags', null=True)
|
||||||
authors = ToManyField(EmailResource, 'authors', null=True)
|
authors = ToManyField(EmailResource, 'authors', null=True)
|
||||||
|
rfc = CharField(attribute='rfc_number', null=True)
|
||||||
class Meta:
|
class Meta:
|
||||||
queryset = Document.objects.all()
|
queryset = Document.objects.all()
|
||||||
#resource_name = 'document'
|
#resource_name = 'document'
|
||||||
|
|
14
ietf/doc/templatetags/active_groups_menu.py
Normal file
14
ietf/doc/templatetags/active_groups_menu.py
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
from django import template
|
||||||
|
from django.template.loader import render_to_string
|
||||||
|
|
||||||
|
from ietf.name.models import GroupTypeName
|
||||||
|
|
||||||
|
register = template.Library()
|
||||||
|
|
||||||
|
@register.simple_tag
|
||||||
|
def active_groups_menu():
|
||||||
|
parents = GroupTypeName.objects.filter(slug__in=['ag','area','team','dir'])
|
||||||
|
for p in parents:
|
||||||
|
p.menu_url = '/%s/'%p.slug
|
||||||
|
return render_to_string('base/menu_active_groups.html', { 'parents': parents })
|
||||||
|
|
|
@ -467,7 +467,7 @@ def collect_email_addresses(emails, doc):
|
||||||
if role.email.address not in emails:
|
if role.email.address not in emails:
|
||||||
emails[role.email.address] = '"%s"' % (role.person.name)
|
emails[role.email.address] = '"%s"' % (role.person.name)
|
||||||
if doc.group.type.slug == 'wg':
|
if doc.group.type.slug == 'wg':
|
||||||
address = '%s-ads@tools.ietf.org' % doc.group.acronym
|
address = '%s-ads@ietf.org' % doc.group.acronym
|
||||||
if address not in emails:
|
if address not in emails:
|
||||||
emails[address] = '"%s-ads"' % (doc.group.acronym)
|
emails[address] = '"%s-ads"' % (doc.group.acronym)
|
||||||
elif doc.group.type.slug == 'rg':
|
elif doc.group.type.slug == 'rg':
|
||||||
|
|
|
@ -13,6 +13,8 @@ from django.contrib.auth.decorators import login_required
|
||||||
from django.template.defaultfilters import pluralize
|
from django.template.defaultfilters import pluralize
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
|
|
||||||
|
import debug # pyflakes:ignore
|
||||||
|
|
||||||
from ietf.doc.models import ( Document, DocAlias, RelatedDocument, State,
|
from ietf.doc.models import ( Document, DocAlias, RelatedDocument, State,
|
||||||
StateType, DocEvent, ConsensusDocEvent, TelechatDocEvent, WriteupDocEvent, IESG_SUBSTATE_TAGS,
|
StateType, DocEvent, ConsensusDocEvent, TelechatDocEvent, WriteupDocEvent, IESG_SUBSTATE_TAGS,
|
||||||
save_document_in_history )
|
save_document_in_history )
|
||||||
|
@ -582,7 +584,7 @@ def to_iesg(request,name):
|
||||||
doc.save()
|
doc.save()
|
||||||
|
|
||||||
extra = {}
|
extra = {}
|
||||||
extra['Cc'] = "%s-chairs@tools.ietf.org, iesg-secretary@ietf.org, %s" % (doc.group.acronym,doc.notify)
|
extra['Cc'] = "%s-chairs@ietf.org, iesg-secretary@ietf.org, %s" % (doc.group.acronym,doc.notify)
|
||||||
send_mail(request=request,
|
send_mail(request=request,
|
||||||
to = doc.ad.email_address(),
|
to = doc.ad.email_address(),
|
||||||
frm = login.formatted_email(),
|
frm = login.formatted_email(),
|
||||||
|
|
|
@ -167,14 +167,29 @@ def get_or_create_initial_charter(group, group_type):
|
||||||
return charter
|
return charter
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def submit_initial_charter(request, group_type, acronym=None):
|
def submit_initial_charter(request, group_type=None, acronym=None):
|
||||||
if not can_manage_group_type(request.user, group_type):
|
|
||||||
return HttpResponseForbidden("You don't have permission to access this view")
|
# This needs refactoring.
|
||||||
|
# The signature assumed you could have groups with the same name, but with different types, which we do not allow.
|
||||||
|
# Consequently, this can be called with an existing group acronym and a type
|
||||||
|
# that doesn't match the existing group type. The code below essentially ignores the group_type argument.
|
||||||
|
#
|
||||||
|
# If possible, the use of get_or_create_initial_charter should be moved
|
||||||
|
# directly into charter_submit, and this function should go away.
|
||||||
|
|
||||||
|
if acronym==None:
|
||||||
|
raise Http404
|
||||||
|
|
||||||
group = get_object_or_404(Group, acronym=acronym)
|
group = get_object_or_404(Group, acronym=acronym)
|
||||||
if not group.features.has_chartering_process:
|
if not group.features.has_chartering_process:
|
||||||
raise Http404
|
raise Http404
|
||||||
|
|
||||||
|
# This is where we start ignoring the passed in group_type
|
||||||
|
group_type = group.type_id
|
||||||
|
|
||||||
|
if not can_manage_group_type(request.user, group_type):
|
||||||
|
return HttpResponseForbidden("You don't have permission to access this view")
|
||||||
|
|
||||||
if not group.charter:
|
if not group.charter:
|
||||||
group.charter = get_or_create_initial_charter(group, group_type)
|
group.charter = get_or_create_initial_charter(group, group_type)
|
||||||
group.save()
|
group.save()
|
||||||
|
|
|
@ -20,6 +20,7 @@ class GroupFeatures(object):
|
||||||
self.default_tab = "group_docs"
|
self.default_tab = "group_docs"
|
||||||
elif group.type_id in ("team",):
|
elif group.type_id in ("team",):
|
||||||
self.has_materials = True
|
self.has_materials = True
|
||||||
|
self.default_tab = "group_about"
|
||||||
|
|
||||||
if self.has_chartering_process:
|
if self.has_chartering_process:
|
||||||
self.about_page = "group_charter"
|
self.about_page = "group_charter"
|
||||||
|
|
|
@ -189,16 +189,43 @@ def wg_charters_by_acronym(request, group_type):
|
||||||
{ 'groups': groups },
|
{ 'groups': groups },
|
||||||
content_type='text/plain; charset=UTF-8')
|
content_type='text/plain; charset=UTF-8')
|
||||||
|
|
||||||
def active_groups(request, group_type):
|
def active_groups(request, group_type=None):
|
||||||
if group_type == "wg":
|
|
||||||
|
if not group_type:
|
||||||
|
return active_group_types(request)
|
||||||
|
elif group_type == "wg":
|
||||||
return active_wgs(request)
|
return active_wgs(request)
|
||||||
elif group_type == "rg":
|
elif group_type == "rg":
|
||||||
return active_rgs(request)
|
return active_rgs(request)
|
||||||
|
elif group_type == "ag":
|
||||||
|
return active_ags(request)
|
||||||
elif group_type == "area":
|
elif group_type == "area":
|
||||||
return active_areas(request)
|
return active_areas(request)
|
||||||
|
elif group_type == "team":
|
||||||
|
return active_teams(request)
|
||||||
|
elif group_type == "dir":
|
||||||
|
return active_dirs(request)
|
||||||
else:
|
else:
|
||||||
raise Http404
|
raise Http404
|
||||||
|
|
||||||
|
def active_group_types(request):
|
||||||
|
grouptypes = GroupTypeName.objects.filter(slug__in=['wg','rg','ag','team','dir','area'])
|
||||||
|
return render(request, 'group/active_groups.html', {'grouptypes':grouptypes})
|
||||||
|
|
||||||
|
def active_dirs(request):
|
||||||
|
dirs = Group.objects.filter(type="dir", state="active").order_by("name")
|
||||||
|
for group in dirs:
|
||||||
|
group.chairs = sorted(roles(group, "chair"), key=extract_last_name)
|
||||||
|
group.ads = sorted(roles(group, "ad"), key=extract_last_name)
|
||||||
|
group.secretaries = sorted(roles(group, "secr"), key=extract_last_name)
|
||||||
|
return render(request, 'group/active_dirs.html', {'dirs' : dirs })
|
||||||
|
|
||||||
|
def active_teams(request):
|
||||||
|
teams = Group.objects.filter(type="team", state="active").order_by("name")
|
||||||
|
for group in teams:
|
||||||
|
group.chairs = sorted(roles(group, "chair"), key=extract_last_name)
|
||||||
|
return render(request, 'group/active_teams.html', {'teams' : teams })
|
||||||
|
|
||||||
def active_areas(request):
|
def active_areas(request):
|
||||||
areas = Group.objects.filter(type="area", state="active").order_by("name")
|
areas = Group.objects.filter(type="area", state="active").order_by("name")
|
||||||
return render(request, 'group/active_areas.html', {'areas': areas })
|
return render(request, 'group/active_areas.html', {'areas': areas })
|
||||||
|
@ -235,6 +262,15 @@ def active_rgs(request):
|
||||||
|
|
||||||
return render(request, 'group/active_rgs.html', { 'irtf': irtf, 'groups': groups })
|
return render(request, 'group/active_rgs.html', { 'irtf': irtf, 'groups': groups })
|
||||||
|
|
||||||
|
def active_ags(request):
|
||||||
|
|
||||||
|
groups = Group.objects.filter(type="ag", state="active").order_by("acronym")
|
||||||
|
for group in groups:
|
||||||
|
group.chairs = sorted(roles(group, "chair"), key=extract_last_name)
|
||||||
|
group.ads = sorted(roles(group, "ad"), key=extract_last_name)
|
||||||
|
|
||||||
|
return render(request, 'group/active_ags.html', { 'groups': groups })
|
||||||
|
|
||||||
def bofs(request, group_type):
|
def bofs(request, group_type):
|
||||||
groups = Group.objects.filter(type=group_type, state="bof")
|
groups = Group.objects.filter(type=group_type, state="bof")
|
||||||
return render(request, 'group/bofs.html',dict(groups=groups))
|
return render(request, 'group/bofs.html',dict(groups=groups))
|
||||||
|
|
|
@ -63,21 +63,25 @@ class GroupTests(TestCase):
|
||||||
make_test_data()
|
make_test_data()
|
||||||
for group in Group.objects.filter(Q(type="wg") | Q(type="rg")):
|
for group in Group.objects.filter(Q(type="wg") | Q(type="rg")):
|
||||||
client = Client(Accept='application/pdf')
|
client = Client(Accept='application/pdf')
|
||||||
r = client.get(urlreverse("ietf.group.info.dependencies_dot",
|
for url in [ urlreverse("ietf.group.info.dependencies_dot",kwargs=dict(acronym=group.acronym)),
|
||||||
kwargs=dict(acronym=group.acronym)))
|
urlreverse("ietf.group.info.dependencies_dot",kwargs=dict(acronym=group.acronym,group_type=group.type_id)),
|
||||||
self.assertTrue(r.status_code == 200, "Failed to receive "
|
]:
|
||||||
"a dot dependency graph for group: %s"%group.acronym)
|
r = client.get(url)
|
||||||
self.assertGreater(len(r.content), 0, "Dot dependency graph for group "
|
self.assertTrue(r.status_code == 200, "Failed to receive "
|
||||||
"%s has no content"%group.acronym)
|
"a dot dependency graph for group: %s"%group.acronym)
|
||||||
|
self.assertGreater(len(r.content), 0, "Dot dependency graph for group "
|
||||||
|
"%s has no content"%group.acronym)
|
||||||
|
|
||||||
def test_group_document_dependency_pdffile(self):
|
def test_group_document_dependency_pdffile(self):
|
||||||
make_test_data()
|
make_test_data()
|
||||||
for group in Group.objects.filter(Q(type="wg") | Q(type="rg")):
|
for group in Group.objects.filter(Q(type="wg") | Q(type="rg")):
|
||||||
client = Client(Accept='application/pdf')
|
client = Client(Accept='application/pdf')
|
||||||
r = client.get(urlreverse("ietf.group.info.dependencies_pdf",
|
for url in [ urlreverse("ietf.group.info.dependencies_pdf",kwargs=dict(acronym=group.acronym)),
|
||||||
kwargs=dict(acronym=group.acronym)))
|
urlreverse("ietf.group.info.dependencies_pdf",kwargs=dict(acronym=group.acronym,group_type=group.type_id)),
|
||||||
self.assertTrue(r.status_code == 200, "Failed to receive "
|
]:
|
||||||
"a pdf dependency graph for group: %s"%group.acronym)
|
r = client.get(url)
|
||||||
self.assertGreater(len(r.content), 0, "Pdf dependency graph for group "
|
self.assertTrue(r.status_code == 200, "Failed to receive "
|
||||||
"%s has no content"%group.acronym)
|
"a pdf dependency graph for group: %s"%group.acronym)
|
||||||
|
self.assertGreater(len(r.content), 0, "Pdf dependency graph for group "
|
||||||
|
"%s has no content"%group.acronym)
|
||||||
|
|
||||||
|
|
|
@ -10,11 +10,12 @@ import debug # pyflakes:ignore
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.core.urlresolvers import reverse as urlreverse
|
from django.core.urlresolvers import reverse as urlreverse
|
||||||
|
from django.core.urlresolvers import NoReverseMatch
|
||||||
|
|
||||||
from ietf.doc.models import Document, DocAlias, DocEvent, State
|
from ietf.doc.models import Document, DocAlias, DocEvent, State
|
||||||
from ietf.group.models import Group, GroupEvent, GroupMilestone, GroupStateTransitions, MilestoneGroupEvent
|
from ietf.group.models import Group, GroupEvent, GroupMilestone, GroupStateTransitions, MilestoneGroupEvent
|
||||||
from ietf.group.utils import save_group_in_history
|
from ietf.group.utils import save_group_in_history
|
||||||
from ietf.name.models import DocTagName, GroupStateName
|
from ietf.name.models import DocTagName, GroupStateName, GroupTypeName
|
||||||
from ietf.person.models import Person, Email
|
from ietf.person.models import Person, Email
|
||||||
from ietf.utils.test_utils import TestCase
|
from ietf.utils.test_utils import TestCase
|
||||||
from ietf.utils.mail import outbox
|
from ietf.utils.mail import outbox
|
||||||
|
@ -48,11 +49,37 @@ class GroupPagesTests(TestCase):
|
||||||
url = urlreverse('ietf.group.info.active_groups', kwargs=dict(group_type="rg"))
|
url = urlreverse('ietf.group.info.active_groups', kwargs=dict(group_type="rg"))
|
||||||
r = self.client.get(url)
|
r = self.client.get(url)
|
||||||
self.assertEqual(r.status_code, 200)
|
self.assertEqual(r.status_code, 200)
|
||||||
|
self.assertTrue('Active Research Groups' in r.content)
|
||||||
|
|
||||||
url = urlreverse('ietf.group.info.active_groups', kwargs=dict(group_type="area"))
|
url = urlreverse('ietf.group.info.active_groups', kwargs=dict(group_type="area"))
|
||||||
r = self.client.get(url)
|
r = self.client.get(url)
|
||||||
self.assertEqual(r.status_code, 200)
|
self.assertEqual(r.status_code, 200)
|
||||||
self.assertTrue("farfut" in r.content)
|
self.assertTrue("Far Future (farfut)" in r.content)
|
||||||
|
|
||||||
|
url = urlreverse('ietf.group.info.active_groups', kwargs=dict(group_type="ag"))
|
||||||
|
r = self.client.get(url)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
self.assertTrue("Active Area Groups" in r.content)
|
||||||
|
|
||||||
|
url = urlreverse('ietf.group.info.active_groups', kwargs=dict(group_type="dir"))
|
||||||
|
r = self.client.get(url)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
self.assertTrue("Active Directorates" in r.content)
|
||||||
|
|
||||||
|
url = urlreverse('ietf.group.info.active_groups', kwargs=dict(group_type="team"))
|
||||||
|
r = self.client.get(url)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
self.assertTrue("Active Teams" in r.content)
|
||||||
|
|
||||||
|
url = urlreverse('ietf.group.info.active_groups', kwargs=dict())
|
||||||
|
r = self.client.get(url)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
self.assertTrue("Directorate" in r.content)
|
||||||
|
self.assertTrue("AG" in r.content)
|
||||||
|
|
||||||
|
for slug in GroupTypeName.objects.exclude(slug__in=['wg','rg','ag','area','dir','team']).values_list('slug',flat=True):
|
||||||
|
with self.assertRaises(NoReverseMatch):
|
||||||
|
url=urlreverse('ietf.group.info.active_groups', kwargs=dict(group_type=slug))
|
||||||
|
|
||||||
def test_wg_summaries(self):
|
def test_wg_summaries(self):
|
||||||
draft = make_test_data()
|
draft = make_test_data()
|
||||||
|
@ -195,14 +222,17 @@ class GroupPagesTests(TestCase):
|
||||||
due=datetime.date.today() + datetime.timedelta(days=100))
|
due=datetime.date.today() + datetime.timedelta(days=100))
|
||||||
milestone.docs.add(draft)
|
milestone.docs.add(draft)
|
||||||
|
|
||||||
url = group.about_url()
|
for url in [group.about_url(),
|
||||||
r = self.client.get(url)
|
urlreverse('ietf.group.info.group_about',kwargs=dict(acronym=group.acronym)),
|
||||||
self.assertEqual(r.status_code, 200)
|
urlreverse('ietf.group.info.group_about',kwargs=dict(acronym=group.acronym,group_type=group.type_id)),
|
||||||
self.assertTrue(group.name in r.content)
|
]:
|
||||||
self.assertTrue(group.acronym in r.content)
|
r = self.client.get(url)
|
||||||
self.assertTrue("This is a charter." in r.content)
|
self.assertEqual(r.status_code, 200)
|
||||||
self.assertTrue(milestone.desc in r.content)
|
self.assertTrue(group.name in r.content)
|
||||||
self.assertTrue(milestone.docs.all()[0].name in r.content)
|
self.assertTrue(group.acronym in r.content)
|
||||||
|
self.assertTrue("This is a charter." in r.content)
|
||||||
|
self.assertTrue(milestone.desc in r.content)
|
||||||
|
self.assertTrue(milestone.docs.all()[0].name in r.content)
|
||||||
|
|
||||||
def test_group_about(self):
|
def test_group_about(self):
|
||||||
make_test_data()
|
make_test_data()
|
||||||
|
@ -214,12 +244,16 @@ class GroupPagesTests(TestCase):
|
||||||
state_id="active",
|
state_id="active",
|
||||||
)
|
)
|
||||||
|
|
||||||
url = group.about_url()
|
for url in [group.about_url(),
|
||||||
r = self.client.get(url)
|
urlreverse('ietf.group.info.group_about',kwargs=dict(acronym=group.acronym)),
|
||||||
self.assertEqual(r.status_code, 200)
|
urlreverse('ietf.group.info.group_about',kwargs=dict(acronym=group.acronym,group_type=group.type_id)),
|
||||||
self.assertTrue(group.name in r.content)
|
]:
|
||||||
self.assertTrue(group.acronym in r.content)
|
url = group.about_url()
|
||||||
self.assertTrue(group.description in r.content)
|
r = self.client.get(url)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
self.assertTrue(group.name in r.content)
|
||||||
|
self.assertTrue(group.acronym in r.content)
|
||||||
|
self.assertTrue(group.description in r.content)
|
||||||
|
|
||||||
def test_materials(self):
|
def test_materials(self):
|
||||||
make_test_data()
|
make_test_data()
|
||||||
|
@ -235,11 +269,15 @@ class GroupPagesTests(TestCase):
|
||||||
doc.set_state(State.objects.get(type="slides", slug="active"))
|
doc.set_state(State.objects.get(type="slides", slug="active"))
|
||||||
DocAlias.objects.create(name=doc.name, document=doc)
|
DocAlias.objects.create(name=doc.name, document=doc)
|
||||||
|
|
||||||
url = urlreverse("group_materials", kwargs={ 'acronym': group.acronym })
|
for url in [ urlreverse("group_materials", kwargs={ 'acronym': group.acronym }),
|
||||||
r = self.client.get(url)
|
urlreverse("group_materials", kwargs={ 'acronym': group.acronym , 'group_type': group.type_id}),
|
||||||
self.assertEqual(r.status_code, 200)
|
]:
|
||||||
self.assertTrue(doc.title in r.content)
|
r = self.client.get(url)
|
||||||
self.assertTrue(doc.name in r.content)
|
self.assertEqual(r.status_code, 200)
|
||||||
|
self.assertTrue(doc.title in r.content)
|
||||||
|
self.assertTrue(doc.name in r.content)
|
||||||
|
|
||||||
|
url = urlreverse("group_materials", kwargs={ 'acronym': group.acronym })
|
||||||
|
|
||||||
# try deleting the document and check it's gone
|
# try deleting the document and check it's gone
|
||||||
doc.set_state(State.objects.get(type="slides", slug="deleted"))
|
doc.set_state(State.objects.get(type="slides", slug="deleted"))
|
||||||
|
@ -475,6 +513,19 @@ class GroupEditTests(TestCase):
|
||||||
self.assertEqual(group.groupurl_set.all()[0].name, "MARS site")
|
self.assertEqual(group.groupurl_set.all()[0].name, "MARS site")
|
||||||
self.assertTrue(os.path.exists(os.path.join(self.charter_dir, "%s-%s.txt" % (group.charter.canonical_name(), group.charter.rev))))
|
self.assertTrue(os.path.exists(os.path.join(self.charter_dir, "%s-%s.txt" % (group.charter.canonical_name(), group.charter.rev))))
|
||||||
|
|
||||||
|
def test_initial_charter(self):
|
||||||
|
make_test_data()
|
||||||
|
group = Group.objects.get(acronym="mars")
|
||||||
|
for url in [ urlreverse('ietf.group.edit.submit_initial_charter', kwargs={'acronym':group.acronym}),
|
||||||
|
urlreverse('ietf.group.edit.submit_initial_charter', kwargs={'acronym':group.acronym,'group_type':group.type_id}),
|
||||||
|
]:
|
||||||
|
login_testing_unauthorized(self, "secretary", url)
|
||||||
|
r = self.client.get(url,follow=True)
|
||||||
|
self.assertEqual(r.status_code,200)
|
||||||
|
self.assertTrue(r.redirect_chain[0][0].endswith(urlreverse('charter_submit',kwargs={'name':group.charter.name,'option':'initcharter'})))
|
||||||
|
self.client.logout()
|
||||||
|
|
||||||
|
|
||||||
def test_conclude(self):
|
def test_conclude(self):
|
||||||
make_test_data()
|
make_test_data()
|
||||||
|
|
||||||
|
@ -998,11 +1049,13 @@ expand-ames-chairs@virtual.ietf.org mars_chair@ietf
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
os.unlink(self.group_alias_file.name)
|
os.unlink(self.group_alias_file.name)
|
||||||
|
|
||||||
def testNothing(self):
|
def testEmailAliases(self):
|
||||||
url = urlreverse('ietf.group.info.email_aliases', kwargs=dict(acronym="mars"))
|
|
||||||
r = self.client.get(url)
|
for testdict in [dict(acronym="mars"),dict(acronym="mars",group_type="wg")]:
|
||||||
self.assertTrue(all([x in r.content for x in ['mars-ads@','mars-chairs@']]))
|
url = urlreverse('ietf.group.info.email_aliases', kwargs=testdict)
|
||||||
self.assertFalse(any([x in r.content for x in ['ames-ads@','ames-chairs@']]))
|
r = self.client.get(url)
|
||||||
|
self.assertTrue(all([x in r.content for x in ['mars-ads@','mars-chairs@']]))
|
||||||
|
self.assertFalse(any([x in r.content for x in ['ames-ads@','ames-chairs@']]))
|
||||||
|
|
||||||
url = urlreverse('ietf.group.info.email_aliases', kwargs=dict())
|
url = urlreverse('ietf.group.info.email_aliases', kwargs=dict())
|
||||||
login_testing_unauthorized(self, "plain", url)
|
login_testing_unauthorized(self, "plain", url)
|
||||||
|
|
|
@ -1,36 +1,18 @@
|
||||||
# Copyright The IETF Trust 2007, All Rights Reserved
|
# Copyright The IETF Trust 2007, All Rights Reserved
|
||||||
|
|
||||||
from django.conf.urls import patterns
|
from django.conf.urls import patterns, include
|
||||||
|
|
||||||
urlpatterns = patterns('',
|
urlpatterns = patterns('',
|
||||||
|
(r'^$', 'ietf.group.info.active_groups'),
|
||||||
(r'^groupmenu.json', 'ietf.group.ajax.group_menu_data', None, "group_menu_data"),
|
(r'^groupmenu.json', 'ietf.group.ajax.group_menu_data', None, "group_menu_data"),
|
||||||
(r'^(?P<acronym>[a-z0-9]+).json$', 'ietf.group.ajax.group_json'),
|
(r'^(?P<acronym>[a-z0-9]+).json$', 'ietf.group.ajax.group_json'),
|
||||||
(r'^chartering/$', 'ietf.group.info.chartering_groups'),
|
(r'^chartering/$', 'ietf.group.info.chartering_groups'),
|
||||||
(r'^chartering/create/(?P<group_type>(wg|rg))/$', 'ietf.group.edit.edit', {'action': "charter"}, "group_create"),
|
(r'^chartering/create/(?P<group_type>(wg|rg))/$', 'ietf.group.edit.edit', {'action': "charter"}, "group_create"),
|
||||||
(r'^concluded/$', 'ietf.group.info.concluded_groups'),
|
(r'^concluded/$', 'ietf.group.info.concluded_groups'),
|
||||||
(r'^email-aliases/$', 'ietf.group.info.email_aliases'),
|
(r'^email-aliases/$', 'ietf.group.info.email_aliases'),
|
||||||
# FIXME: the things below are duplicated in urls_info.py while we
|
|
||||||
# figure out whether to serve everything from /group/<acronym>,
|
|
||||||
# need to unify these at some point
|
|
||||||
(r'^(?P<acronym>[a-zA-Z0-9-._]+)/$', 'ietf.group.info.group_home', None, "group_home"),
|
|
||||||
(r'^(?P<acronym>[a-zA-Z0-9-._]+)/documents/$', 'ietf.group.info.group_documents', None, "group_docs"),
|
|
||||||
(r'^(?P<acronym>[a-zA-Z0-9-._]+)/charter/$', 'ietf.group.info.group_about', None, 'group_charter'),
|
|
||||||
(r'^(?P<acronym>[a-zA-Z0-9-._]+)/history/$', 'ietf.group.info.history'),
|
|
||||||
(r'^(?P<acronym>[a-zA-Z0-9-._]+)/deps/dot/$', 'ietf.group.info.dependencies_dot'),
|
|
||||||
(r'^(?P<acronym>[a-zA-Z0-9-._]+)/deps/pdf/$', 'ietf.group.info.dependencies_pdf'),
|
|
||||||
(r'^(?P<acronym>[a-zA-Z0-9-._]+)/init-charter/', 'ietf.group.edit.submit_initial_charter'),
|
|
||||||
(r'^(?P<acronym>[a-zA-Z0-9-._]+)/edit/$', 'ietf.group.edit.edit', {'action': "edit"}, "group_edit"),
|
|
||||||
(r'^(?P<acronym>[a-zA-Z0-9-._]+)/conclude/$', 'ietf.group.edit.conclude'),
|
|
||||||
(r'^(?P<acronym>[a-zA-Z0-9-._]+)/milestones/$', 'ietf.group.milestones.edit_milestones', {'milestone_set': "current"}, "group_edit_milestones"),
|
|
||||||
(r'^(?P<acronym>[a-zA-Z0-9-._]+)/milestones/charter/$', 'ietf.group.milestones.edit_milestones', {'milestone_set': "charter"}, "group_edit_charter_milestones"),
|
|
||||||
(r'^(?P<acronym>[a-zA-Z0-9-._]+)/milestones/charter/reset/$', 'ietf.group.milestones.reset_charter_milestones', None, "group_reset_charter_milestones"),
|
|
||||||
(r'^(?P<acronym>[a-zA-Z0-9-._]+)/workflow/$', 'ietf.group.edit.customize_workflow'),
|
|
||||||
|
|
||||||
(r'^(?P<acronym>[a-zA-Z0-9-._]+)/about/(?P<group_type>.)?$', 'ietf.group.info.group_about', None, 'group_about'),
|
(r'^(?P<acronym>[a-zA-Z0-9-._]+)/$', 'ietf.group.info.group_home', None, "group_home"),
|
||||||
(r'^(?P<acronym>[a-zA-Z0-9-._]+)/materials/$', 'ietf.group.info.materials', None, "group_materials"),
|
(r'^(?P<acronym>[a-zA-Z0-9-._]+)/', include('ietf.group.urls_info_details')),
|
||||||
(r'^(?P<acronym>[a-zA-Z0-9-._]+)/materials/new/$', 'ietf.doc.views_material.choose_material_type'),
|
|
||||||
(r'^(?P<acronym>[a-zA-Z0-9-._]+)/materials/new/(?P<doc_type>[\w-]+)/$', 'ietf.doc.views_material.edit_material', { 'action': "new" }, "group_new_material"),
|
|
||||||
(r'^(?P<acronym>[A-Za-z0-9._+-]+)/email-aliases/$', 'ietf.group.info.email_aliases'),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
# Copyright The IETF Trust 2008, All Rights Reserved
|
# Copyright The IETF Trust 2008, All Rights Reserved
|
||||||
|
|
||||||
from django.conf.urls import patterns
|
from django.conf.urls import patterns, include
|
||||||
from django.views.generic import RedirectView
|
from django.views.generic import RedirectView
|
||||||
|
|
||||||
from ietf.group import info, edit, milestones
|
from ietf.group import info, edit
|
||||||
|
|
||||||
urlpatterns = patterns('',
|
urlpatterns = patterns('',
|
||||||
(r'^$', info.active_groups),
|
(r'^$', info.active_groups),
|
||||||
(r'^summary.txt', RedirectView.as_view(url='/wg/1wg-summary.txt')),
|
(r'^summary.txt', RedirectView.as_view(url='/wg/1wg-summary.txt')),
|
||||||
(r'^summary-by-area.txt', RedirectView.as_view(url='/wg/1wg-summary.txt')),
|
(r'^summary-by-area.txt', RedirectView.as_view(url='/wg/1wg-summary.txt')),
|
||||||
(r'^summary-by-acronym.txt', RedirectView.as_view(url='/wg/1wg-summary-by-acronym.txt')),
|
(r'^summary-by-acronym.txt', RedirectView.as_view(url='/wg/1wg-summary-by-acronym.txt')),
|
||||||
|
@ -19,19 +19,5 @@ urlpatterns = patterns('',
|
||||||
(r'^bofs/$', info.bofs),
|
(r'^bofs/$', info.bofs),
|
||||||
(r'^email-aliases/$', 'ietf.group.info.email_aliases'),
|
(r'^email-aliases/$', 'ietf.group.info.email_aliases'),
|
||||||
(r'^bofs/create/$', edit.edit, {'action': "create"}, "bof_create"),
|
(r'^bofs/create/$', edit.edit, {'action': "create"}, "bof_create"),
|
||||||
(r'^(?P<acronym>[a-zA-Z0-9-._]+)/documents/txt/$', info.group_documents_txt),
|
(r'^(?P<acronym>[a-zA-Z0-9-._]+)/', include('ietf.group.urls_info_details')),
|
||||||
(r'^(?P<acronym>[a-zA-Z0-9-._]+)/$', info.group_home, None, "group_home"),
|
|
||||||
(r'^(?P<acronym>[a-zA-Z0-9-._]+)/documents/$', info.group_documents, None, "group_docs"),
|
|
||||||
(r'^(?P<acronym>[a-zA-Z0-9-._]+)/charter/$', info.group_about, None, 'group_charter'),
|
|
||||||
(r'^(?P<acronym>[a-zA-Z0-9-._]+)/history/$', info.history),
|
|
||||||
(r'^(?P<acronym>[a-zA-Z0-9-._]+)/deps/dot/$', info.dependencies_dot),
|
|
||||||
(r'^(?P<acronym>[a-zA-Z0-9-._]+)/deps/pdf/$', info.dependencies_pdf),
|
|
||||||
(r'^(?P<acronym>[a-zA-Z0-9-._]+)/init-charter/', edit.submit_initial_charter),
|
|
||||||
(r'^(?P<acronym>[a-zA-Z0-9-._]+)/edit/$', edit.edit, {'action': "edit"}, "group_edit"),
|
|
||||||
(r'^(?P<acronym>[a-zA-Z0-9-._]+)/conclude/$', edit.conclude),
|
|
||||||
(r'^(?P<acronym>[a-zA-Z0-9-._]+)/milestones/$', milestones.edit_milestones, {'milestone_set': "current"}, "group_edit_milestones"),
|
|
||||||
(r'^(?P<acronym>[a-zA-Z0-9-._]+)/milestones/charter/$', milestones.edit_milestones, {'milestone_set': "charter"}, "group_edit_charter_milestones"),
|
|
||||||
(r'^(?P<acronym>[a-zA-Z0-9-._]+)/milestones/charter/reset/$', milestones.reset_charter_milestones, None, "group_reset_charter_milestones"),
|
|
||||||
(r'^(?P<acronym>[a-zA-Z0-9-._]+)/workflow/$', edit.customize_workflow),
|
|
||||||
(r'^(?P<acronym>[A-Za-z0-9._+-]+)/email-aliases/$', 'ietf.group.info.email_aliases'),
|
|
||||||
)
|
)
|
||||||
|
|
23
ietf/group/urls_info_details.py
Normal file
23
ietf/group/urls_info_details.py
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
from django.conf.urls import patterns
|
||||||
|
|
||||||
|
urlpatterns = patterns('',
|
||||||
|
(r'^$', 'ietf.group.info.group_home', None, "group_home"),
|
||||||
|
(r'^documents/txt/$', 'ietf.group.info.group_documents_txt'),
|
||||||
|
(r'^documents/$', 'ietf.group.info.group_documents', None, "group_docs"),
|
||||||
|
(r'^charter/$', 'ietf.group.info.group_about', None, 'group_charter'),
|
||||||
|
(r'^about/$', 'ietf.group.info.group_about', None, 'group_about'),
|
||||||
|
(r'^history/$','ietf.group.info.history'),
|
||||||
|
(r'^deps/dot/$', 'ietf.group.info.dependencies_dot'),
|
||||||
|
(r'^deps/pdf/$', 'ietf.group.info.dependencies_pdf'),
|
||||||
|
(r'^init-charter/', 'ietf.group.edit.submit_initial_charter'),
|
||||||
|
(r'^edit/$', 'ietf.group.edit.edit', {'action': "edit"}, "group_edit"),
|
||||||
|
(r'^conclude/$', 'ietf.group.edit.conclude'),
|
||||||
|
(r'^milestones/$', 'ietf.group.milestones.edit_milestones', {'milestone_set': "current"}, "group_edit_milestones"),
|
||||||
|
(r'^milestones/charter/$', 'ietf.group.milestones.edit_milestones', {'milestone_set': "charter"}, "group_edit_charter_milestones"),
|
||||||
|
(r'^milestones/charter/reset/$', 'ietf.group.milestones.reset_charter_milestones', None, "group_reset_charter_milestones"),
|
||||||
|
(r'^workflow/$', 'ietf.group.edit.customize_workflow'),
|
||||||
|
(r'^materials/$', 'ietf.group.info.materials', None, "group_materials"),
|
||||||
|
(r'^materials/new/$', 'ietf.doc.views_material.choose_material_type'),
|
||||||
|
(r'^materials/new/(?P<doc_type>[\w-]+)/$', 'ietf.doc.views_material.edit_material', { 'action': "new" }, "group_new_material"),
|
||||||
|
(r'^/email-aliases/$', 'ietf.group.info.email_aliases'),
|
||||||
|
)
|
|
@ -147,7 +147,7 @@ def get_fullcc_list(draft):
|
||||||
emails[role.email.address] = '"%s"' % (role.person.name)
|
emails[role.email.address] = '"%s"' % (role.person.name)
|
||||||
# add AD
|
# add AD
|
||||||
if draft.group.type.slug == 'wg':
|
if draft.group.type.slug == 'wg':
|
||||||
emails['%s-ads@tools.ietf.org' % draft.group.acronym] = '"%s-ads"' % (draft.group.acronym)
|
emails['%s-ads@ietf.org' % draft.group.acronym] = '"%s-ads"' % (draft.group.acronym)
|
||||||
elif draft.group.type.slug == 'rg':
|
elif draft.group.type.slug == 'rg':
|
||||||
email = draft.group.parent.role_set.filter(name='chair')[0].email
|
email = draft.group.parent.role_set.filter(name='chair')[0].email
|
||||||
emails[email.address] = '"%s"' % (email.person.name)
|
emails[email.address] = '"%s"' % (email.person.name)
|
||||||
|
|
|
@ -45,7 +45,7 @@ def check_audio_files(group,meeting):
|
||||||
continue
|
continue
|
||||||
room = timeslot.location.name.lower()
|
room = timeslot.location.name.lower()
|
||||||
room = room.replace(' ','')
|
room = room.replace(' ','')
|
||||||
room = room.replace('/','')
|
room = room.replace('/','_')
|
||||||
time = timeslot.time.strftime("%Y%m%d-%H%M")
|
time = timeslot.time.strftime("%Y%m%d-%H%M")
|
||||||
filename = 'ietf{}-{}-{}-*'.format(meeting.number,room,time)
|
filename = 'ietf{}-{}-{}-*'.format(meeting.number,room,time)
|
||||||
path = os.path.join(settings.MEETING_RECORDINGS_DIR,'ietf{}'.format(meeting.number),filename)
|
path = os.path.join(settings.MEETING_RECORDINGS_DIR,'ietf{}'.format(meeting.number),filename)
|
||||||
|
|
|
@ -6,7 +6,7 @@ def get_ad_email_list(group):
|
||||||
'''
|
'''
|
||||||
emails = []
|
emails = []
|
||||||
if group.type.slug == 'wg':
|
if group.type.slug == 'wg':
|
||||||
emails.append('%s-ads@tools.ietf.org' % group.acronym)
|
emails.append('%s-ads@ietf.org' % group.acronym)
|
||||||
elif group.type.slug == 'rg' and group.parent:
|
elif group.type.slug == 'rg' and group.parent:
|
||||||
emails.append(group.parent.role_set.filter(name='chair')[0].email.address)
|
emails.append(group.parent.role_set.filter(name='chair')[0].email.address)
|
||||||
return emails
|
return emails
|
||||||
|
|
|
@ -136,7 +136,8 @@ class SubmissionUploadForm(forms.Form):
|
||||||
if self.cleaned_data.get('xml'):
|
if self.cleaned_data.get('xml'):
|
||||||
#if not self.cleaned_data.get('txt'):
|
#if not self.cleaned_data.get('txt'):
|
||||||
xml_file = self.cleaned_data.get('xml')
|
xml_file = self.cleaned_data.get('xml')
|
||||||
tfh, tfn = tempfile.mkstemp(suffix='.xml')
|
name, ext = os.path.splitext(os.path.basename(xml_file.name))
|
||||||
|
tfh, tfn = tempfile.mkstemp(prefix=name+'-', suffix='.xml')
|
||||||
try:
|
try:
|
||||||
# We need to write the xml file to disk in order to hand it
|
# We need to write the xml file to disk in order to hand it
|
||||||
# over to the xml parser. XXX FIXME: investigate updating
|
# over to the xml parser. XXX FIXME: investigate updating
|
||||||
|
@ -150,7 +151,19 @@ class SubmissionUploadForm(forms.Form):
|
||||||
self.xmltree = parser.parse()
|
self.xmltree = parser.parse()
|
||||||
ok, errors = self.xmltree.validate()
|
ok, errors = self.xmltree.validate()
|
||||||
if not ok:
|
if not ok:
|
||||||
raise forms.ValidationError(errors)
|
# Each error has properties:
|
||||||
|
#
|
||||||
|
# message: the message text
|
||||||
|
# domain: the domain ID (see lxml.etree.ErrorDomains)
|
||||||
|
# type: the message type ID (see lxml.etree.ErrorTypes)
|
||||||
|
# level: the log level ID (see lxml.etree.ErrorLevels)
|
||||||
|
# line: the line at which the message originated (if applicable)
|
||||||
|
# column: the character column at which the message originated (if applicable)
|
||||||
|
# filename: the name of the file in which the message originated (if applicable)
|
||||||
|
raise forms.ValidationError(
|
||||||
|
[ forms.ValidationError("One or more XML validation errors occurred when processing the XML file:") ] +
|
||||||
|
[ forms.ValidationError("%s: Line %s: %s" % (xml_file.name, e.line, e.message), code="%s"%e.type) for e in errors ]
|
||||||
|
)
|
||||||
self.xmlroot = self.xmltree.getroot()
|
self.xmlroot = self.xmltree.getroot()
|
||||||
draftname = self.xmlroot.attrib.get('docName')
|
draftname = self.xmlroot.attrib.get('docName')
|
||||||
revmatch = re.search("-[0-9][0-9]$", draftname)
|
revmatch = re.search("-[0-9][0-9]$", draftname)
|
||||||
|
@ -160,22 +173,24 @@ class SubmissionUploadForm(forms.Form):
|
||||||
else:
|
else:
|
||||||
self.revision = None
|
self.revision = None
|
||||||
self.filename = draftname
|
self.filename = draftname
|
||||||
self.title = self.xmlroot.find('front/title').text
|
self.title = self.xmlroot.findtext('front/title')
|
||||||
self.abstract = self.xmlroot.find('front/abstract').text
|
self.abstract = self.xmlroot.findtext('front/abstract')
|
||||||
self.author_list = []
|
self.author_list = []
|
||||||
author_info = self.xmlroot.findall('front/author')
|
author_info = self.xmlroot.findall('front/author')
|
||||||
for author in author_info:
|
for author in author_info:
|
||||||
author_dict = dict(
|
author_dict = dict(
|
||||||
company = author.find('organization').text,
|
company = author.findtext('organization'),
|
||||||
last_name = author.attrib.get('surname'),
|
last_name = author.attrib.get('surname'),
|
||||||
full_name = author.attrib.get('fullname'),
|
full_name = author.attrib.get('fullname'),
|
||||||
email = author.find('address/email').text,
|
email = author.findtext('address/email'),
|
||||||
)
|
)
|
||||||
self.author_list.append(author_dict)
|
self.author_list.append(author_dict)
|
||||||
line = "%(full_name)s <%(email)s>" % author_dict
|
line = "%(full_name)s <%(email)s>" % author_dict
|
||||||
self.authors.append(line)
|
self.authors.append(line)
|
||||||
|
except forms.ValidationError:
|
||||||
|
raise
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise forms.ValidationError("Exception: %s" % e)
|
raise forms.ValidationError("Exception when trying to process the XML file: %s" % e)
|
||||||
finally:
|
finally:
|
||||||
os.close(tfh)
|
os.close(tfh)
|
||||||
os.unlink(tfn)
|
os.unlink(tfn)
|
||||||
|
|
|
@ -77,4 +77,4 @@ class FileParser(object):
|
||||||
content = self.fd.file.read(4096)
|
content = self.fd.file.read(4096)
|
||||||
mimetype = magic.from_buffer(content, mime=True)
|
mimetype = magic.from_buffer(content, mime=True)
|
||||||
if not mimetype == expected:
|
if not mimetype == expected:
|
||||||
self.parsed_info.add_error('Expected an %s file of type "%s", found one of type "%s"' % (expected, mimetype))
|
self.parsed_info.add_error('Expected an %s file of type "%s", found one of type "%s"' % (ext.upper(), expected, mimetype))
|
||||||
|
|
|
@ -47,13 +47,13 @@ def upload_submission(request):
|
||||||
|
|
||||||
if form.cleaned_data['xml']:
|
if form.cleaned_data['xml']:
|
||||||
if not form.cleaned_data['txt']:
|
if not form.cleaned_data['txt']:
|
||||||
|
file_name['txt'] = os.path.join(settings.IDSUBMIT_STAGING_PATH, '%s-%s.txt' % (form.filename, form.revision))
|
||||||
try:
|
try:
|
||||||
file_name['txt'] = os.path.join(settings.IDSUBMIT_STAGING_PATH, '%s-%s.txt' % (form.filename, form.revision))
|
|
||||||
pagedwriter = xml2rfc.PaginatedTextRfcWriter(form.xmltree, quiet=True)
|
pagedwriter = xml2rfc.PaginatedTextRfcWriter(form.xmltree, quiet=True)
|
||||||
pagedwriter.write(file_name['txt'])
|
pagedwriter.write(file_name['txt'])
|
||||||
file_size = os.stat(file_name['txt']).st_size
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise ValidationError("Exception: %s" % e)
|
raise ValidationError("Error from xml2rfc: %s" % e)
|
||||||
|
file_size = os.stat(file_name['txt']).st_size
|
||||||
# Some meta-information, such as the page-count, can only
|
# Some meta-information, such as the page-count, can only
|
||||||
# be retrieved from the generated text file. Provide a
|
# be retrieved from the generated text file. Provide a
|
||||||
# parsed draft object to get at that kind of information.
|
# parsed draft object to get at that kind of information.
|
||||||
|
@ -128,6 +128,10 @@ def upload_submission(request):
|
||||||
form._errors["__all__"] = form.error_class(["There was a failure receiving the complete form data -- please try again."])
|
form._errors["__all__"] = form.error_class(["There was a failure receiving the complete form data -- please try again."])
|
||||||
else:
|
else:
|
||||||
raise
|
raise
|
||||||
|
except ValidationError as e:
|
||||||
|
form = SubmissionUploadForm(request=request)
|
||||||
|
form._errors = {}
|
||||||
|
form._errors["__all__"] = form.error_class(["There was a failure converting the xml file to text -- please verify that your xml file is valid. (%s)" % e.message])
|
||||||
else:
|
else:
|
||||||
form = SubmissionUploadForm(request=request)
|
form = SubmissionUploadForm(request=request)
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{# Copyright The IETF Trust 2015, All Rights Reserved #}{% load origin %}{% origin %}
|
{# Copyright The IETF Trust 2015, All Rights Reserved #}{% load origin %}{% origin %}
|
||||||
{% load ietf_filters community_tags wg_menu streams_menu %}
|
{% load ietf_filters community_tags wg_menu streams_menu active_groups_menu %}
|
||||||
|
|
||||||
{% if flavor != "top" %}
|
{% if flavor != "top" %}
|
||||||
{% include "base/menu_user.html" %}
|
{% include "base/menu_user.html" %}
|
||||||
|
@ -14,9 +14,9 @@
|
||||||
<ul class="dropdown-menu" role="menu">
|
<ul class="dropdown-menu" role="menu">
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<li><a href="{% url "ietf.group.info.active_groups" group_type="area" %}">Active areas</a></li>
|
|
||||||
<li><a href="{% url "ietf.group.info.active_groups" group_type="wg" %}">Active WGs</a></li>
|
<li><a href="{% url "ietf.group.info.active_groups" group_type="wg" %}">Active WGs</a></li>
|
||||||
<li><a href="{% url "ietf.group.info.active_groups" group_type="rg" %}">Active RGs</a></li>
|
<li><a href="{% url "ietf.group.info.active_groups" group_type="rg" %}">Active RGs</a></li>
|
||||||
|
<li class="dropdown-submenu group-menu"><a href="{% url "ietf.group.info.active_groups" %}">Other</a>{% active_groups_menu %} </li>
|
||||||
|
|
||||||
{% if flavor == "top" %}<li class="divider visible-lg-block"></li>{% endif %}
|
{% if flavor == "top" %}<li class="divider visible-lg-block"></li>{% endif %}
|
||||||
<li {%if flavor == "top" %}class="dropdown-header visible-lg-block"{% else %}class="nav-header hidden-nojs"{% endif %}>By area/parent</li>
|
<li {%if flavor == "top" %}class="dropdown-header visible-lg-block"{% else %}class="nav-header hidden-nojs"{% endif %}>By area/parent</li>
|
||||||
|
|
8
ietf/templates/base/menu_active_groups.html
Normal file
8
ietf/templates/base/menu_active_groups.html
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
{# Copyright The IETF Trust 2015, All Rights Reserved #}{% load origin %}{% origin %}
|
||||||
|
<ul class="dropdown-menu" role="menu">
|
||||||
|
{% for p in parents %}
|
||||||
|
<li>
|
||||||
|
<a href="{{ p.menu_url }}">Active {{ p.name }}s</a>
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
|
@ -413,7 +413,7 @@
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<div class="buttonlist">
|
<div class="buttonlist">
|
||||||
<a class="btn btn-default btn-xs" href="mailto:{{ doc.name }}@tools.ietf.org?subject=Mail%20regarding%20{{ doc.name }}"><span class="fa fa-envelope-o"></span> Email authors</a>
|
<a class="btn btn-default btn-xs" href="mailto:{{ doc.name }}@ietf.org?subject=Mail%20regarding%20{{ doc.name }}"><span class="fa fa-envelope-o"></span> Email authors</a>
|
||||||
<a class="btn btn-default btn-xs" href="{% url "ipr_search" %}?submit=draft&id={{ doc.name }}" rel="nofollow"><span class="fa fa-bolt"></span> IPR {% if doc.related_ipr %} <span class="badge">{{doc.related_ipr|length}}</span>{% endif %}</a>
|
<a class="btn btn-default btn-xs" href="{% url "ipr_search" %}?submit=draft&id={{ doc.name }}" rel="nofollow"><span class="fa fa-bolt"></span> IPR {% if doc.related_ipr %} <span class="badge">{{doc.related_ipr|length}}</span>{% endif %}</a>
|
||||||
<a class="btn btn-default btn-xs" href="{% url "doc_references" doc.canonical_name %}" rel="nofollow"><span class="fa fa-long-arrow-left"></span> References</a>
|
<a class="btn btn-default btn-xs" href="{% url "doc_references" doc.canonical_name %}" rel="nofollow"><span class="fa fa-long-arrow-left"></span> References</a>
|
||||||
<a class="btn btn-default btn-xs" href="{% url "doc_referenced_by" doc.canonical_name %}" rel="nofollow"><span class="fa fa-long-arrow-right"></span> Referenced by</a>
|
<a class="btn btn-default btn-xs" href="{% url "doc_referenced_by" doc.canonical_name %}" rel="nofollow"><span class="fa fa-long-arrow-right"></span> Referenced by</a>
|
||||||
|
|
45
ietf/templates/group/active_ags.html
Normal file
45
ietf/templates/group/active_ags.html
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
{# Copyright The IETF Trust 2015, All Rights Reserved #}
|
||||||
|
{% load origin %}
|
||||||
|
|
||||||
|
{% block title %}Active Area Groups{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
{% origin %}
|
||||||
|
<h1>Active Area Groups</h1>
|
||||||
|
<table class="table table-condensed table-striped">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Team</th>
|
||||||
|
<th>Name</th>
|
||||||
|
<th>AD</th>
|
||||||
|
<th>Secretaries</th>
|
||||||
|
<th>Chairs</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for group in groups %}
|
||||||
|
<tr>
|
||||||
|
<td><a href="{% url "ietf.group.info.group_home" acronym=group.acronym %}">{{ group.acronym }}</a></td>
|
||||||
|
<td>{{ group.name }}</td>
|
||||||
|
<td>
|
||||||
|
{% for ad in group.ads %}
|
||||||
|
<a href="mailto:{{ ad.email.address }}">{{ ad.person.plain_name }}</a>{% if not forloop.last %}, {% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{% for secretary in group.secretaries %}
|
||||||
|
<a href="mailto:{{ secretary.email.address }}">{{ secretary.person.plain_name }}</a>{% if not forloop.last %}, {% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{% for chair in group.chairs %}
|
||||||
|
<a href="mailto:{{ chair.email.address }}">{{ chair.person.plain_name }}</a>{% if not forloop.last %}, {% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
{% endblock %}
|
||||||
|
|
|
@ -12,11 +12,11 @@
|
||||||
<p>When changing the area structure, the IESG can decide which members are responsible for new and changed areas, including making one sitting AD responsible for multiple areas, but the IESG can only add new members through the <a href="https://www.ietf.org/nomcom/index.html">nomcom process</a>.</p>
|
<p>When changing the area structure, the IESG can decide which members are responsible for new and changed areas, including making one sitting AD responsible for multiple areas, but the IESG can only add new members through the <a href="https://www.ietf.org/nomcom/index.html">nomcom process</a>.</p>
|
||||||
<p>The primary task of area management is handled by one or two Area Directors per area. An AD may be advised by one or more directorates, which are created, selected, chaired and if necessary disbanded by the AD. Directorates may be specific to an area, specific to a technology, or chartered in some other fashion.</p>
|
<p>The primary task of area management is handled by one or two Area Directors per area. An AD may be advised by one or more directorates, which are created, selected, chaired and if necessary disbanded by the AD. Directorates may be specific to an area, specific to a technology, or chartered in some other fashion.</p>
|
||||||
<p>The ADs for an area are jointly responsible for making sure the WGs in the area are well coordinated, that there is coverage for the technologies needed in the area, and that the challenges most important to the Internet in that area are indeed being worked on.</p>
|
<p>The ADs for an area are jointly responsible for making sure the WGs in the area are well coordinated, that there is coverage for the technologies needed in the area, and that the challenges most important to the Internet in that area are indeed being worked on.</p>
|
||||||
<ul><li>A full list of active working groups, sorted by area, may be found at <a href="https://datatracker.ietf.org/wg/">https://datatracker.ietf.org/wg/</a>.</li></ul>
|
<ul><li>A full list of active working groups, sorted by area, may be found at <a href="{% url 'ietf.group.info.active_groups' group_type='wg'%}">{% url 'ietf.group.info.active_groups' group_type='wg' %}</a>.</li></ul>
|
||||||
<p>The IESG decides which areas working groups belong to. The charter of each area is listed below.</p>
|
<p>The IESG decides which areas working groups belong to. The charter of each area is listed below.</p>
|
||||||
|
|
||||||
{% for area in areas %}
|
{% for area in areas %}
|
||||||
<h2>{{area.name}} ({{area.acronym}})</h2>
|
<h2><a href="{%url 'ietf.group.info.active_groups' group_type='wg'%}#{{area.acronym}}">{{area.name}} ({{area.acronym}})</a></h2>
|
||||||
<pre class="pasted">{{area.description}}</pre>
|
<pre class="pasted">{{area.description}}</pre>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
<p>For more information about the role of the IESG in areas and working groups, please see <a href="https://www.ietf.org/rfc/rfc3710.txt">RFC 3710 ("An IESG charter")</a>, section 6 and <a href="https://www.ietf.org/rfc/rfc2418.txt">RFC 2418 ("IETF Working Group Guidelines and Procedures")</a>.</p>
|
<p>For more information about the role of the IESG in areas and working groups, please see <a href="https://www.ietf.org/rfc/rfc3710.txt">RFC 3710 ("An IESG charter")</a>, section 6 and <a href="https://www.ietf.org/rfc/rfc2418.txt">RFC 2418 ("IETF Working Group Guidelines and Procedures")</a>.</p>
|
||||||
|
|
46
ietf/templates/group/active_dirs.html
Normal file
46
ietf/templates/group/active_dirs.html
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
{# Copyright The IETF Trust 2015, All Rights Reserved #}
|
||||||
|
{% load origin %}
|
||||||
|
|
||||||
|
{% block title %}Active Directorates{% endblock %}
|
||||||
|
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
{% origin %}
|
||||||
|
<h1>Active Directorates</h1>
|
||||||
|
<table class="table table-condensed table-striped">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Team</th>
|
||||||
|
<th>Name</th>
|
||||||
|
<th>AD</th>
|
||||||
|
<th>Secretaries</th>
|
||||||
|
<th>Chairs</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for group in dirs %}
|
||||||
|
<tr>
|
||||||
|
<td><a href="{% url "ietf.group.info.group_home" acronym=group.acronym %}">{{ group.acronym }}</a></td>
|
||||||
|
<td>{{ group.name }}</td>
|
||||||
|
<td>
|
||||||
|
{% for ad in group.ads %}
|
||||||
|
<a href="mailto:{{ ad.email.address }}">{{ ad.person.plain_name }}</a>{% if not forloop.last %}, {% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{% for secretary in group.secretaries %}
|
||||||
|
<a href="mailto:{{ secretary.email.address }}">{{ secretary.person.plain_name }}</a>{% if not forloop.last %}, {% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{% for chair in group.chairs %}
|
||||||
|
<a href="mailto:{{ chair.email.address }}">{{ chair.person.plain_name }}</a>{% if not forloop.last %}, {% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
{% endblock %}
|
||||||
|
|
27
ietf/templates/group/active_groups.html
Normal file
27
ietf/templates/group/active_groups.html
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
{# Copyright The IETF Trust 2015, All Rights Reserved #}
|
||||||
|
{% load origin %}
|
||||||
|
|
||||||
|
{% block title %}Active Groups{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
{% origin %}
|
||||||
|
<h1>Active Groups</h1>
|
||||||
|
<table class="table table-condensed table-striped">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Type</th>
|
||||||
|
<th>Description</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for typename in grouptypes %}
|
||||||
|
<tr>
|
||||||
|
<td><a href="{% url "ietf.group.info.active_groups" group_type=typename.slug%}">{{ typename.name }}</a></td>
|
||||||
|
<td>{{ typename.desc }}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
{% endblock %}
|
||||||
|
|
34
ietf/templates/group/active_teams.html
Normal file
34
ietf/templates/group/active_teams.html
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
{# Copyright The IETF Trust 2015, All Rights Reserved #}
|
||||||
|
{% load origin %}
|
||||||
|
|
||||||
|
{% block title %}Active Teams{% endblock %}
|
||||||
|
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
{% origin %}
|
||||||
|
<h1>Active Teams</h1>
|
||||||
|
<table class="table table-condensed table-striped">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Team</th>
|
||||||
|
<th>Name</th>
|
||||||
|
<th>Chairs</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for group in teams %}
|
||||||
|
<tr>
|
||||||
|
<td><a href="{% url "ietf.group.info.group_home" acronym=group.acronym %}">{{ group.acronym }}</a></td>
|
||||||
|
<td>{{ group.name }}</td>
|
||||||
|
<td>
|
||||||
|
{% for chair in group.chairs %}
|
||||||
|
<a href="mailto:{{ chair.email.address }}">{{ chair.person.plain_name }}</a>{% if not forloop.last %}, {% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
{% endblock %}
|
|
@ -90,7 +90,7 @@
|
||||||
<p>Please make sure that your Internet-Draft includes all of the required meta-data in the proper format.</p>
|
<p>Please make sure that your Internet-Draft includes all of the required meta-data in the proper format.</p>
|
||||||
|
|
||||||
<p>If your Internet-Draft <b>does</b> include all of the required meta-data in the proper format, and if
|
<p>If your Internet-Draft <b>does</b> include all of the required meta-data in the proper format, and if
|
||||||
the error(s) identified above are due to the failure of the tool to extract the meta-data correctly,
|
the error(s) identified below are due to the failure of the tool to extract the meta-data correctly,
|
||||||
then please use the "Adjust meta-data" button below, which will take you to the "Adjust screen" where
|
then please use the "Adjust meta-data" button below, which will take you to the "Adjust screen" where
|
||||||
you can correct the improperly extracted meta-data. You will then be able to submit your Internet-Draft
|
you can correct the improperly extracted meta-data. You will then be able to submit your Internet-Draft
|
||||||
to the Secretariat for manual posting.</p>
|
to the Secretariat for manual posting.</p>
|
||||||
|
|
|
@ -54,7 +54,7 @@ urlpatterns = patterns('',
|
||||||
(r'^sync/', include('ietf.sync.urls')),
|
(r'^sync/', include('ietf.sync.urls')),
|
||||||
(r'^stream/', include('ietf.group.urls_stream')),
|
(r'^stream/', include('ietf.group.urls_stream')),
|
||||||
(r'^templates/', include('ietf.dbtemplate.urls')),
|
(r'^templates/', include('ietf.dbtemplate.urls')),
|
||||||
(r'^(?P<group_type>(wg|rg|area))/', include('ietf.group.urls_info')),
|
(r'^(?P<group_type>(wg|rg|ag|team|dir|area))/', include('ietf.group.urls_info')),
|
||||||
|
|
||||||
# Redirects
|
# Redirects
|
||||||
(r'^(?P<path>public)/', include('ietf.redirects.urls')),
|
(r'^(?P<path>public)/', include('ietf.redirects.urls')),
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,4 +1,6 @@
|
||||||
# -*- conf-mode -*-
|
# -*- conf-mode -*-
|
||||||
|
setuptools>=1.2 # Require this first, to prevent later errors
|
||||||
|
#
|
||||||
coverage>=3.7.1
|
coverage>=3.7.1
|
||||||
#cssselect>=0.6.1 # for PyQuery
|
#cssselect>=0.6.1 # for PyQuery
|
||||||
decorator>=3.4.0
|
decorator>=3.4.0
|
||||||
|
@ -19,7 +21,6 @@ python-dateutil>=2.2
|
||||||
python-magic>=0.4.6
|
python-magic>=0.4.6
|
||||||
python-memcached>=1.48 # for django.core.cache.backends.memcached
|
python-memcached>=1.48 # for django.core.cache.backends.memcached
|
||||||
pytz>=2014.7
|
pytz>=2014.7
|
||||||
setuptools>=1.2
|
|
||||||
six>=1.8.0
|
six>=1.8.0
|
||||||
wsgiref>=0.1.2
|
wsgiref>=0.1.2
|
||||||
xml2rfc>=2.5.0
|
xml2rfc>=2.5.0
|
||||||
|
|
Loading…
Reference in a new issue