Added corrections and tests as discussed with Ole.

- Legacy-Id: 3349
This commit is contained in:
Martin Qvist 2011-08-22 19:54:25 +00:00
parent 0a34a909c0
commit b73c5358e7
33 changed files with 587 additions and 142 deletions

View file

@ -177,6 +177,8 @@ MAX_WG_DELEGATES = 3
INTERNET_DRAFT_PATH = '/a/www/ietf-ftp/internet-drafts/'
INTERNET_DRAFT_PDF_PATH = '/a/www/ietf-datatracker/pdf/'
RFC_PATH = '/a/www/ietf-ftp/rfc/'
CHARTER_PATH = '/a/www/ietf-ftp/charters/'
CHARTER_TXT_URL = 'http://www.ietf.org/charters/'
AGENDA_PATH = '/a/www/www6s/proceedings/'
AGENDA_PATH_PATTERN = '/a/www/www6s/proceedings/%(meeting)s/agenda/%(wg)s.%(ext)s'
MINUTES_PATH_PATTERN = '/a/www/www6s/proceedings/%(meeting)s/minutes/%(wg)s.%(ext)s'

View file

@ -27,7 +27,7 @@ form.add-comment .actions {
<tr>
<td></td>
<td class="actions">
<a href="{% url record_view name=wg.acronym %}">Back</a>
<a href="{% url wg_view_record name=wg.acronym %}">Back</a>
<input type="submit" value="Add comment"/>
</td>
</tr>

View file

@ -30,7 +30,7 @@ form.approve-ballot .announcement {
</div>
<div class="actions">
<a href="{% url record_view name=wg.acronym %}">Back</a>
<a href="{% url wg_view_record name=wg.acronym %}">Back</a>
<input type="submit" value="Send out the announcement, close ballot and update revision"/>
</div>
</form>

View file

@ -43,7 +43,7 @@ form.change-state .actions {
{% endfor %}
<tr>
<td colspan="2" class="actions">
<a href="{% url record_view name=wg.acronym %}">Back</a>
<a href="{% url wg_view_record name=wg.acronym %}">Back</a>
<input type="submit" value="Save"/>
</td>
</tr>
@ -68,10 +68,9 @@ form.change-state .actions {
var message = {
"infrev": "The WG {{ wg.name }} ({{ wg.acronym }}) has been set to Informal IESG review by {{ login.name }}",
"intrev": "The WG {{ wg.name }} ({{ wg.acronym }}) has been set to Internal review by {{ login.name }}. Please place it on the next IESG telechat and inform the IAB.",
"extrev": "The WG {{ wg.name }} ({{ wg.acronym }}) has been set to External review by {{ login.name }}. Please send out the external review announcement to the appropriate lists.\n\nSend the announcement to other SDOs: Yes\nAdditional recipients of the announcement: ",
"approved": "The WG {{ wg.name }} ({{ wg.acronym }}) has been approved. Please publish the charter and sent the appropriate announcements."
"extrev": "The WG {{ wg.name }} ({{ wg.acronym }}) has been set to External review by {{ login.name }}. Please send out the external review announcement to the appropriate lists.\n\nSend the announcement to other SDOs: Yes\nAdditional recipients of the announcement: "
};
</script>
<script type="text/javascript" src="/js/rec-change-state.js"></script>
<script type="text/javascript" src="/js/wg-change-state.js"></script>
{% endblock %}

View file

@ -3,7 +3,7 @@
{% block title %}Request closing of WG {{ wg.acronym }}{% endblock %}
{% block morecss %}
#id_comment {
#id_instructions {
width: 40em;
}
@ -28,7 +28,7 @@ form.conclude .actions {
{{ form.as_table }}
<tr>
<td colspan="2" class="actions">
<a href="{% url record_view name=wg.acronym %}">Back</a>
<a href="{% url wg_view_record name=wg.acronym %}">Back</a>
<input type="submit" value="Send request"/>
</td>
</tr>

View file

@ -78,7 +78,7 @@ Create WG record
<td></td>
<td class="actions">
{% if wg %}
<a href="{% url record_view name=wg.acronym %}">Back</a>
<a href="{% url wg_view_record name=wg.acronym %}">Back</a>
{% endif %}
<input type="submit" value="Save"/>
</td>

View file

@ -71,5 +71,5 @@ form.position-form .comment {
{% endblock %}
{% block content_end %}
<script type="text/javascript" src="/js/rec-edit-position.js"></script>
<script type="text/javascript" src="/js/wg-edit-position.js"></script>
{% endblock %}

View file

@ -6,10 +6,10 @@ Copyright The IETF Trust 2011, All Rights Reserved
{% if user|in_group:"Area_Director,Secretariat" %}
{% if user|in_group:"Area_Director" %}
<div style="margin-top:8px; margin-bottom:8px;"><span id="rec_ballot_button" class="yui-button yui-link-button"><span class="first-child"><a href="{% url rec_edit_position name=wg.acronym %}">Edit position</a></span></span></div>
<div style="margin-top:8px; margin-bottom:8px;"><span id="wg_ballot_button" class="yui-button yui-link-button"><span class="first-child"><a href="{% url wg_edit_position name=wg.acronym %}">Edit position</a></span></span></div>
{% endif %}
{% if user|in_group:"Secretariat" %}
<div style="margin-top:8px; margin-bottom:8px;"><span id="rec_ballot_button" class="yui-button yui-link-button"><span class="first-child"><a href="{% url rec_approve_ballot name=wg.acronym %}">Approve ballot</a></span></span></div>
<div style="margin-top:8px; margin-bottom:8px;"><span id="wg_ballot_button" class="yui-button yui-link-button"><span class="first-child"><a href="{% url wg_approve_ballot name=wg.acronym %}">Approve ballot</a></span></span></div>
{% endif %}
{% endif %}
@ -27,7 +27,7 @@ Copyright The IETF Trust 2011, All Rights Reserved
<p><span class="square" style="background:white;"></span><b>No Record</b><br/>
{% for p in info.pos_no_record %}
<a{% if user|in_group:"Secretariat" %} href="{% url rec_edit_position name=wg.acronym %}?ad={{ p.id }}" title="Click to edit the position of {{ p.name }}"{% endif %}>{{p.name}}</a><br/>
<a{% if user|in_group:"Secretariat" %} href="{% url wg_edit_position name=wg.acronym %}?ad={{ p.id }}" title="Click to edit the position of {{ p.name }}"{% endif %}>{{p.name}}{% if user|in_group:"Secretariat" %}</a>{% endif %}<br/>
{% empty %}
<i>none</i>
{% endfor %}

View file

@ -1,6 +1,6 @@
{% load ietf_filters %}
{% for p in positions %}
{% if p.is_old_ad %}[{%endif%}<a{% if user|in_group:"Secretariat" %} href="{% url rec_edit_position name=wg.acronym %}?ad={{ p.ad_id }}" title="Click to edit the position of {{ p.ad }}"{% endif %}>{{p.ad}}</a>{% if p.is_old_ad %}]{%endif%}{% if p.comment or p.block_comment %}&nbsp;<a href="#{{p.ad|slugify}}"><img src="/images/comment.png" width="14" height="12" alt="*" border="0"/></a>{% endif %}<br/>
{% if p.is_old_ad %}[{%endif%}<a{% if user|in_group:"Secretariat" %} href="{% url wg_edit_position name=wg.acronym %}?ad={{ p.ad_id }}" title="Click to edit the position of {{ p.ad }}"{% endif %}>{{p.ad}}</a>{% if p.is_old_ad %}]{%endif%}{% if p.comment or p.block_comment %}&nbsp;<a href="#{{p.ad|slugify}}"><img src="/images/comment.png" width="14" height="12" alt="*" border="0"/></a>{% endif %}<br/>
{% if p.old_positions %}<span class="was">(was {{p.old_positions|join:", "}})</span><br/>{%endif%}
{% empty %}
<i>none</i>

View file

@ -7,7 +7,7 @@ Copyright The IETF Trust 2011, All Rights Reserved
{% load ietf_filters %}
{% block record_revision %}
Snapshots: {% if not snapshot %}<strong>{% else %}<a href="{% url record_view name=wg.acronym %}">{% endif %}current{% if not snapshot %}</strong>{% else %}</a>{% endif %} {% for d in versions reversed %}{% ifnotequal d.rev wg.charter.rev %}{% ifequal snapshot d.rev %}<strong>{% else %}<a href="{% url record_view name=wg.acronym %}{{d.rev}}/">{% endifequal %}{{ d.rev }}{% ifequal snapshot d.rev %}</strong>{% else %}</a>{% endifequal %} {% endifnotequal %}{% endfor %}
Snapshots: {% if not snapshot %}<strong>{% else %}<a href="{% url wg_view_record name=wg.acronym %}">{% endif %}current{% if not snapshot %}</strong>{% else %}</a>{% endif %} {% for d in versions reversed %}{% ifnotequal d.rev wg.charter.rev %}{% ifequal snapshot d.rev %}<strong>{% else %}<a href="{% url wg_view_record name=wg.acronym %}{{d.rev}}/">{% endifequal %}{{ d.rev }}{% ifequal snapshot d.rev %}</strong>{% else %}</a>{% endifequal %} {% endifnotequal %}{% endfor %}
{% endblock %}
{% block record_metatable %}

View file

@ -10,7 +10,7 @@ Copyright The IETF Trust 2011, All Rights Reserved
<h2 style="margin-top:1em;">WG History</h2>
{% if user|in_group:"Area_Director,Secretariat" %}
<div style="margin-bottom:8px" id="history_actions">
<span id="rec_add_comment_button" class="yui-button yui-link-button" style="margin-left:2px;"><span class="first-child"><a href="{% url rec_add_comment name=wg.acronym %}">Add comment</a></span></span>
<span id="wg_add_comment_button" class="yui-button yui-link-button" style="margin-left:2px;"><span class="first-child"><a href="{% url wg_add_comment name=wg.acronym %}">Add comment</a></span></span>
</div>
{% endif %}

View file

@ -10,8 +10,8 @@ Copyright The IETF Trust 2011, All Rights Reserved
{% if user|in_group:"Area_Director,Secretariat" %}
<div style="background:#E0E0FF">
<p align=right>
<span id="rec_edit_announce_button" class="yui-button yui-link-button"><span class="first-child">
<a href="{% url rec_announcement_text name=wg.acronym ann="review" %}">Edit WG Review Announcement</a>
<span id="wg_edit_announce_button" class="yui-button yui-link-button"><span class="first-child">
<a href="{% url wg_announcement_text name=wg.acronym ann="review" %}">Edit WG Review Announcement</a>
</span></span>
</p>
{% endif %}
@ -24,8 +24,8 @@ Copyright The IETF Trust 2011, All Rights Reserved
{% if user|in_group:"Area_Director,Secretariat" %}
<div style="background:#E0E0FF">
<p align=right>
<span id="rec_edit_announce_button" class="yui-button yui-link-button"><span class="first-child">
<a href="{% url rec_announcement_text name=wg.acronym ann="action" %}">Edit WG Action Announcement</a>
<span id="wg_edit_announce_button" class="yui-button yui-link-button"><span class="first-child">
<a href="{% url wg_announcement_text name=wg.acronym ann="action" %}">Edit WG Action Announcement</a>
</span></span>
</p>
{% endif %}

View file

@ -5,7 +5,7 @@ Copyright The IETF Trust 2011, All Rights Reserved
{% load ietf_filters %}
<tr class="{% cycle oddrow,evenrow %}">
<td class="acronym">
<a href="{% url record_view name=wg.acronym %}">{{ wg.acronym|safe }}</a>
<a href="{% url wg_view_record name=wg.acronym %}">{{ wg.acronym|safe }}</a>
</td>
<td class="title">{{ wg.name }}</td>
{% include "wgrecord/date_column.html" %}

View file

@ -1,7 +1,7 @@
{% comment %}
Copyright The IETF Trust 2011, All Rights Reserved
{% endcomment %}
{% load ietf_filters ietf_streams %}{% load rec_ballot_icon %}
{% load ietf_filters ietf_streams %}{% load wg_ballot_icon %}
<td class="status">
{% if wg.charter %}
{{ wg.charter.charter_state|safe }}
@ -13,5 +13,5 @@ Copyright The IETF Trust 2011, All Rights Reserved
{% block extra_status %}{% endblock %}
</td>
<td class="ballot">
{% ifequal wg.charter.charter_state_id "iesgrev" %}{% rec_ballot_icon wg.acronym %}{% endifequal %}
{% ifequal wg.charter.charter_state_id "iesgrev" %}{% wg_ballot_icon wg.acronym %}{% endifequal %}
</td>

View file

@ -40,7 +40,7 @@ Charter submission for {{ wg.acronym }}
<tr>
<td></td>
<td class="actions">
<a href="{% url record_view name=wg.acronym %}">Back</a>
<a href="{% url wg_view_record name=wg.acronym %}">Back</a>
<input type="submit" value="Submit"/>
</td>
</tr>

View file

@ -60,6 +60,20 @@ def make_test_data():
group=area,
email=email)
# ex-ad
u = User.objects.create(username="exad")
ad = p = Person.objects.create(
name="Exaread Irector",
ascii="Exaread Irector",
user=u)
email = Email.objects.create(
address="exaread@ietf.org",
person=p)
Role.objects.create(
name_id="ex-ad",
group=area,
email=email)
# create a bunch of ads for swarm tests
for i in range(1, 10):
u = User.objects.create(username="ad%s" % i)

View file

@ -28,7 +28,7 @@ class GroupComments(Feed):
def link(self, obj):
if obj is None:
raise FeedDoesNotExist
return reverse('record_view', kwargs={'name': obj.acronym})
return reverse('wg_view_record', kwargs={'name': obj.acronym})
def description(self, obj):
return self.title(obj)
@ -38,13 +38,13 @@ class GroupComments(Feed):
for h in history:
gh = find_history_active_at(obj, h['date'])
if gh:
h['chairs'] = map(lambda x: x.email.person.name, gh.rolehistory_set.filter(name__slug="chair"))
h['secr'] = map(lambda x: x.email.person.name, gh.rolehistory_set.filter(name__slug="secr"))
h['techadv'] = map(lambda x: x.email.person.name, gh.rolehistory_set.filter(name__slug="techadv"))
h['chairs'] = [x.email.person.name for x in gh.rolehistory_set.filter(name__slug="chair")]
h['secr'] = [x.email.person.name for x in gh.rolehistory_set.filter(name__slug="secr")]
h['techadv'] = [x.email.person.name for x in gh.rolehistory_set.filter(name__slug="techadv")]
else:
h['chairs'] = map(lambda x: x.email.person.name, obj.role_set.filter(name__slug="chair"))
h['secr'] = map(lambda x: x.email.person.name, obj.role_set.filter(name__slug="secr"))
h['techadv'] = map(lambda x: x.email.person.name, obj.role_set.filter(name__slug="techadv"))
h['chairs'] = [x.email.person.name for x in obj.role_set.filter(name__slug="chair")]
h['secr'] = [x.email.person.name for x in obj.role_set.filter(name__slug="secr")]
h['techadv'] = [x.email.person.name for x in obj.role_set.filter(name__slug="techadv")]
dh = find_history_active_at(obj.charter, h['date'])
if dh:
h['rev'] = dh.rev
@ -59,7 +59,7 @@ class GroupComments(Feed):
return history
def item_link(self, obj):
return reverse('record_view', kwargs={'name': obj['group'].acronym})
return reverse('wg_view_record', kwargs={'name': obj['group'].acronym})
def item_pubdate(self, obj):
return obj['date']

View file

@ -32,5 +32,5 @@ def email_secretariat(request, wg, type, text):
"Regarding WG %s: %s" % (wg.acronym, types[type]),
"wgrecord/email_secretariat.txt",
dict(text=text,
url=settings.IDTRACKER_BASE_URL + urlreverse('record_view', kwargs=dict(name=wg.acronym))))
url=settings.IDTRACKER_BASE_URL + urlreverse('wg_view_record', kwargs=dict(name=wg.acronym))))

0
ietf/wgrecord/models.py Normal file
View file

View file

@ -42,11 +42,7 @@ def render_ballot_icon(context, name):
latest_positions = []
for p in active_ads:
p_pos = list(GroupBallotPositionDocEvent.objects.filter(doc=doc, ad=p).order_by("-time"))
if p_pos == []:
pos = GroupBallotPositionDocEvent(doc=doc, ad=p, by=p)
pos.save()
latest_positions.append(pos)
else:
if p_pos != []:
latest_positions.append(p_pos[0])
for p in latest_positions:
if not p.pos_id:
@ -66,12 +62,12 @@ def render_ballot_icon(context, name):
return render_ballot_icon2(wg.acronym, red,yellow,green,gray,blank, my, adId)+"<!-- adId="+str(adId)+" my="+str(my)+"-->"
def render_ballot_icon2(acronym, red,yellow,green,gray,blank, my, adId):
edit_position_url = urlreverse('rec_edit_position', kwargs=dict(name=acronym))
edit_position_url = urlreverse('wg_edit_position', kwargs=dict(name=acronym))
if adId:
res_cm = ' oncontextmenu="editRecBallot(\''+str(edit_position_url)+'\');return false;"'
res_cm = ' oncontextmenu="editWGBallot(\''+str(edit_position_url)+'\');return false;"'
else:
res_cm = ''
res = '<table class="ballot_icon" title="IESG Review (click to show more, right-click to edit position)" onclick="showRecBallot(\'' + acronym + '\',\'' + str(edit_position_url) + '\')"'+res_cm+'>'
res = '<table class="ballot_icon" title="IESG Review (click to show more, right-click to edit position)" onclick="showWGBallot(\'' + acronym + '\',\'' + str(edit_position_url) + '\')"'+res_cm+'>'
for y in range(3):
res = res + "<tr>"
for x in range(5):
@ -115,7 +111,7 @@ def do_ballot_icon(parser, token):
raise template.TemplateSyntaxError, "%r tag requires exactly two arguments" % token.contents.split()[0]
return BallotIconNode(docName)
register.tag('rec_ballot_icon', do_ballot_icon)
register.tag('wg_ballot_icon', do_ballot_icon)
@register.filter
def my_position(doc, user):

View file

@ -2,14 +2,40 @@
import os
import unittest
import django.test
from django.conf import settings
from ietf.utils.test_utils import SimpleUrlTestCase
from ietf.utils.test_runner import mail_outbox
from ietf.utils.test_data import make_test_data
from ietf.utils.test_utils import SimpleUrlTestCase, RealDatabaseTest, login_testing_unauthorized
class WgRecUrlTestCase(SimpleUrlTestCase):
import datetime
from pyquery import PyQuery
from tempfile import NamedTemporaryFile
from django.contrib.auth.models import User
from doc.models import *
from group.models import *
from name.models import *
from person.models import *
from name.utils import name
from utils import *
class WgUrlTestCase(SimpleUrlTestCase):
def testUrls(self):
self.doTestUrls(__file__)
class WgRecFileTestCase(unittest.TestCase):
def setUp(self, *args, **kwargs):
super(WgUrlTestCase, self).setUp(*args, **kwargs)
# Make test data (because we use the new schema)
make_test_data()
# Make sure all relevant names are created
type_charter = name(DocTypeName, "charter", "Charter")
active = name(GroupStateName, "active", "Active")
approved = name(CharterDocStateName, "approved", "Approved")
class WgFileTestCase(django.test.TestCase):
def testFileExistence(self):
print " Testing if WG charter texts exist locally"
fpath = os.path.join(settings.CHARTER_PATH, "charter-ietf-example-01.txt")
@ -19,4 +45,317 @@ class WgRecFileTestCase(unittest.TestCase):
print "Remember to set CHARTER_PATH in settings_local.py\n"
else:
print "OK (seem to exist)"
class WgStateTestCase(django.test.TestCase):
fixtures = ['names']
def test_change_state(self):
make_test_data()
# Make sure all relevant names are created
type_charter = name(DocTypeName, "charter", "Charter")
active = name(GroupStateName, "active", "Active")
notrev=name(CharterDocStateName, slug="notrev", name="Not currently under review")
infrev=name(CharterDocStateName, slug="infrev", name="Informal IESG review")
intrev=name(CharterDocStateName, slug="intrev", name="Internal review")
extrev=name(CharterDocStateName, slug="extrev", name="External review")
iesgrev=name(CharterDocStateName, slug="iesgrev", name="IESG review")
approved=name(CharterDocStateName, slug="approved", name="Approved")
# And make a charter for group
group = Group.objects.get(acronym="mars")
charter = set_or_create_charter(group)
charter.charter_state = infrev
charter.save()
# -- Test change state --
url = urlreverse('wg_change_state', kwargs=dict(name=group.acronym))
login_testing_unauthorized(self, "secretary", url)
first_state = charter.charter_state
# normal get
r = self.client.get(url)
self.assertEquals(r.status_code, 200)
q = PyQuery(r.content)
self.assertEquals(len(q('form select[name=state]')), 1)
# faulty post
r = self.client.post(url, dict(state="foobarbaz"))
self.assertEquals(r.status_code, 200)
q = PyQuery(r.content)
self.assertTrue(len(q('form ul.errorlist')) > 0)
self.assertEquals(charter.charter_state, first_state)
# change state
for s in ("intrev", "extrev", "iesgrev", "approved"):
events_before = charter.docevent_set.count()
mailbox_before = len(mail_outbox)
r = self.client.post(url, dict(state="active", charter_state=s, message="test message"))
self.assertEquals(r.status_code, 302)
charter = Document.objects.get(name="charter-ietf-%s" % group.acronym)
self.assertEquals(charter.charter_state_id, s)
self.assertEquals(charter.docevent_set.count(), events_before + 1)
self.assertTrue("State changed" in charter.docevent_set.all()[0].desc)
if s == "extrev":
self.assertEquals(len(mail_outbox), mailbox_before + 2)
self.assertTrue("State changed" in mail_outbox[-1]['Subject'])
self.assertTrue("State changed" in mail_outbox[-2]['Subject'])
else:
self.assertEquals(len(mail_outbox), mailbox_before + 1)
if s == "approved":
self.assertTrue("Charter approved" in mail_outbox[-1]['Subject'])
else:
self.assertTrue("State changed" in mail_outbox[-1]['Subject'])
def test_conclude(self):
make_test_data()
# Make sure all relevant names are created
type_charter = name(DocTypeName, "charter", "Charter")
active = name(GroupStateName, "active", "Active")
notrev=name(CharterDocStateName, slug="notrev", name="Not currently under review")
infrev=name(CharterDocStateName, slug="infrev", name="Informal IESG review")
intrev=name(CharterDocStateName, slug="intrev", name="Internal review")
extrev=name(CharterDocStateName, slug="extrev", name="External review")
iesgrev=name(CharterDocStateName, slug="iesgrev", name="IESG review")
approved=name(CharterDocStateName, slug="approved", name="Approved")
# And make a charter for group
group = Group.objects.get(acronym="mars")
charter = set_or_create_charter(group)
charter.charter_state = approved
charter.save()
# -- Test conclude WG --
url = urlreverse('wg_conclude', kwargs=dict(name=group.acronym))
login_testing_unauthorized(self, "secretary", url)
# normal get
r = self.client.get(url)
self.assertEquals(r.status_code, 200)
q = PyQuery(r.content)
self.assertEquals(len(q('form textarea[name=instructions]')), 1)
# faulty post
r = self.client.post(url, dict(instructions="")) # No instructions
self.assertEquals(r.status_code, 200)
q = PyQuery(r.content)
self.assertTrue(len(q('form ul.errorlist')) > 0)
group = Group.objects.get(acronym="mars")
# conclusion request
r = self.client.post(url, dict(instructions="Test instructions"))
self.assertEquals(r.status_code, 302)
# The WG remains active until the state is set to conclude via change_state
self.assertEquals(group.state_id, "active")
class WgInfoTestCase(django.test.TestCase):
fixtures = ['names']
def test_create(self):
make_test_data()
# Make sure all relevant names are created
type_charter = name(DocTypeName, "charter", "Charter")
active = name(GroupStateName, "active", "Active")
notrev=name(CharterDocStateName, slug="notrev", name="Not currently under review")
infrev=name(CharterDocStateName, slug="infrev", name="Informal IESG review")
intrev=name(CharterDocStateName, slug="intrev", name="Internal review")
extrev=name(CharterDocStateName, slug="extrev", name="External review")
iesgrev=name(CharterDocStateName, slug="iesgrev", name="IESG review")
approved=name(CharterDocStateName, slug="approved", name="Approved")
# -- Test WG creation --
url = urlreverse('wg_create')
login_testing_unauthorized(self, "secretary", url)
num_wgs = len(Group.objects.filter(type="wg"))
# normal get
r = self.client.get(url)
self.assertEquals(r.status_code, 200)
q = PyQuery(r.content)
self.assertEquals(len(q('form input[name=acronym]')), 1)
# faulty post
r = self.client.post(url, dict(acronym="foobarbaz")) # No name
self.assertEquals(r.status_code, 200)
q = PyQuery(r.content)
self.assertTrue(len(q('form ul.errorlist')) > 0)
self.assertEquals(len(Group.objects.filter(type="wg")), num_wgs)
# creation
r = self.client.post(url, dict(acronym="testwg", name="Testing WG"))
self.assertEquals(r.status_code, 302)
self.assertEquals(len(Group.objects.filter(type="wg")), num_wgs + 1)
group = Group.objects.get(acronym="testwg")
self.assertEquals(group.name, "Testing WG")
# check that a charter was created with the correct name
self.assertEquals(group.charter.name, "charter-ietf-testwg")
# and that it has no revision
self.assertEquals(group.charter.rev, "")
def test_edit_info(self):
make_test_data()
# Make sure all relevant names are created
type_charter = name(DocTypeName, "charter", "Charter")
active = name(GroupStateName, "active", "Active")
notrev=name(CharterDocStateName, slug="notrev", name="Not currently under review")
infrev=name(CharterDocStateName, slug="infrev", name="Informal IESG review")
intrev=name(CharterDocStateName, slug="intrev", name="Internal review")
extrev=name(CharterDocStateName, slug="extrev", name="External review")
iesgrev=name(CharterDocStateName, slug="iesgrev", name="IESG review")
approved=name(CharterDocStateName, slug="approved", name="Approved")
# And make a charter for group
group = Group.objects.get(acronym="mars")
charter = set_or_create_charter(group)
url = urlreverse('wg_edit_info', kwargs=dict(name=group.acronym))
login_testing_unauthorized(self, "secretary", url)
# normal get
r = self.client.get(url)
self.assertEquals(r.status_code, 200)
q = PyQuery(r.content)
self.assertEquals(len(q('form select[name=parent]')), 1)
self.assertEquals(len(q('form input[name=acronym]')), 1)
# faulty post
Group.objects.create(name="Collision Test Group", acronym="collide")
r = self.client.post(url, dict(acronym="collide"))
self.assertEquals(r.status_code, 200)
q = PyQuery(r.content)
self.assertTrue(len(q('form ul.errorlist')) > 0)
# Create old acronym
group.acronym = "oldmars"
group.save()
save_group_in_history(group)
group.acronym = "mars"
group.save()
# post with warning
r = self.client.post(url, dict(acronym="oldmars"))
self.assertEquals(r.status_code, 200)
q = PyQuery(r.content)
self.assertTrue(len(q('form ul.errorlist')) > 0)
# edit info
r = self.client.post(url,
dict(name="Mars Not Special Interest Group",
acronym="mnsig",
parent=2,
ad=1,
chairs="aread@ietf.org",
secr="aread@ietf.org",
techadv="aread@ietf.org",
list_email="mars@mail",
list_subscribe="subscribe.mars",
list_archive="archive.mars",
urls="http://mars.mars (MARS site)"
))
self.assertEquals(r.status_code, 302)
group = Group.objects.get(acronym="mnsig")
self.assertEquals(group.name, "Mars Not Special Interest Group")
self.assertEquals(group.parent_id, 2)
self.assertEquals(group.ad.name, "Aread Irector")
for k in ("chair", "secr", "techadv"):
self.assertEquals(group.role_set.filter(name="chair")[0].email.address, "aread@ietf.org")
self.assertEquals(group.list_email, "mars@mail")
self.assertEquals(group.list_subscribe, "subscribe.mars")
self.assertEquals(group.list_archive, "archive.mars")
self.assertEquals(group.groupurl_set.all()[0].url, "http://mars.mars")
self.assertEquals(group.groupurl_set.all()[0].name, "MARS site")
def test_edit_telechat_date(self):
make_test_data()
# Make sure all relevant names are created
type_charter = name(DocTypeName, "charter", "Charter")
active = name(GroupStateName, "active", "Active")
notrev=name(CharterDocStateName, slug="notrev", name="Not currently under review")
infrev=name(CharterDocStateName, slug="infrev", name="Informal IESG review")
intrev=name(CharterDocStateName, slug="intrev", name="Internal review")
extrev=name(CharterDocStateName, slug="extrev", name="External review")
iesgrev=name(CharterDocStateName, slug="iesgrev", name="IESG review")
approved=name(CharterDocStateName, slug="approved", name="Approved")
# And make a charter for group
group = Group.objects.get(acronym="mars")
charter = set_or_create_charter(group)
url = urlreverse('wg_edit_info', kwargs=dict(name=group.acronym))
login_testing_unauthorized(self, "secretary", url)
from ietf.iesg.models import TelechatDates
# add to telechat
self.assertTrue(not charter.latest_event(TelechatDocEvent, "scheduled_for_telechat"))
telechat_date = TelechatDates.objects.all()[0].date1.isoformat()
r = self.client.post(url, dict(name=group.name, acronym=group.acronym, telechat_date=telechat_date))
self.assertEquals(r.status_code, 302)
charter = Document.objects.get(name=charter.name)
self.assertTrue(charter.latest_event(TelechatDocEvent, "scheduled_for_telechat"))
self.assertEquals(charter.latest_event(TelechatDocEvent, "scheduled_for_telechat").telechat_date, TelechatDates.objects.all()[0].date1)
# change telechat
telechat_date = TelechatDates.objects.all()[0].date2.isoformat()
r = self.client.post(url, dict(name=group.name, acronym=group.acronym, telechat_date=telechat_date))
self.assertEquals(r.status_code, 302)
charter = Document.objects.get(name=charter.name)
self.assertEquals(charter.latest_event(TelechatDocEvent, "scheduled_for_telechat").telechat_date, TelechatDates.objects.all()[0].date2)
# remove from agenda
telechat_date = ""
r = self.client.post(url, dict(name=group.name, acronym=group.acronym, telechat_date=telechat_date))
self.assertEquals(r.status_code, 302)
charter = Document.objects.get(name=charter.name)
self.assertTrue(not charter.latest_event(TelechatDocEvent, "scheduled_for_telechat").telechat_date)
def test_submit_charter(self):
make_test_data()
# Make sure all relevant names are created
type_charter = name(DocTypeName, "charter", "Charter")
active = name(GroupStateName, "active", "Active")
notrev=name(CharterDocStateName, slug="notrev", name="Not currently under review")
infrev=name(CharterDocStateName, slug="infrev", name="Informal IESG review")
intrev=name(CharterDocStateName, slug="intrev", name="Internal review")
extrev=name(CharterDocStateName, slug="extrev", name="External review")
iesgrev=name(CharterDocStateName, slug="iesgrev", name="IESG review")
approved=name(CharterDocStateName, slug="approved", name="Approved")
# And make a charter for group
group = Group.objects.get(acronym="mars")
charter = set_or_create_charter(group)
url = urlreverse('wg_submit', kwargs=dict(name=group.acronym))
login_testing_unauthorized(self, "secretary", url)
# normal get
r = self.client.get(url)
self.assertEquals(r.status_code, 200)
q = PyQuery(r.content)
self.assertEquals(len(q('form input[name=txt]')), 1)
prev_rev = charter.rev
file = NamedTemporaryFile()
file.write("Test content")
file.seek(0)
r = self.client.post(url, dict(txt=file))
self.assertEquals(r.status_code, 302)
file.close()
charter = Document.objects.get(name="charter-ietf-mars")
self.assertEquals(charter.rev, next_revision(prev_rev))
self.assertTrue("new_revision" in charter.latest_event().type)

View file

@ -0,0 +1,55 @@
200 /
200 /wgrecord/
# In IESG process
200 /wgrecord/in_process/
# by AD
# current AD -- needs to be updated at some point
200 /wgrecord/ad/aread.irector/
# former AD
200 /wgrecord/ad/exaread.irector/
404 /wgrecord/ad/no.body/
# create
302 /wgrecord/create/
# WG
200 /wgrecord/mars/
200 /wgrecord/mars/00-00/
200 /wgrecord/mars/_ballot.data
# Edit WG
302 /wgrecord/mars/edit/state/
302 /wgrecord/mars/edit/info/
302 /wgrecord/mars/edit/conclude/
302 /wgrecord/mars/edit/addcomment/
302 /wgrecord/mars/edit/action/
302 /wgrecord/mars/edit/review/
# ballots
302 /wgrecord/mars/edit/position/
302 /wgrecord/mars/edit/sendballotcomment/
302 /wgrecord/mars/edit/approveballot/
# submission of charters
302 /wgrecord/mars/submit/
# search
200 /wgrecord/search/
302 /wgrecord/search/?name=martian
200 /wgrecord/search/?name=something
200 /wgrecord/search/?name=something&by=acronym&acronym=some
200 /wgrecord/search/?name=something&by=state&state=active&charter_state=
200 /wgrecord/search/?name=something&by=state&state=&charter_state=approved
200 /wgrecord/search/?name=something&by=ad&ad=1
200 /wgrecord/search/?name=something&by=area&area=2
200 /wgrecord/search/?name=something&by=anyfield&anyfield=something
200 /wgrecord/search/?name=something&by=eacronym&eacronym=someold
# searchPerson (ajax)
200 /wgrecord/searchPerson/
#

View file

@ -14,16 +14,16 @@ urlpatterns += patterns('',
(r'^searchPerson/$', views_search.search_person),
url(r'^ad/(?P<name>[A-Za-z0-9.-]+)/$', views_search.by_ad, name="wg_search_by_ad"),
url(r'^in_process/$', views_search.in_process, name="wg_search_in_process"),
url(r'^(?P<name>[A-Za-z0-9._-]+)/((?P<rev>[0-9][0-9](-[0-9][0-9])?)/)?((?P<tab>ballot|writeup|history)/)?$', views_rec.record_main, name="record_view"),
(r'^(?P<name>[A-Za-z0-9._-]+)/_ballot.data$', views_rec.record_ballot),
url(r'^(?P<name>[A-Za-z0-9._-]+)/((?P<rev>[0-9][0-9](-[0-9][0-9])?)/)?((?P<tab>ballot|writeup|history)/)?$', views_rec.wg_main, name="wg_view_record"),
(r'^(?P<name>[A-Za-z0-9._-]+)/_ballot.data$', views_rec.wg_ballot),
url(r'^(?P<name>[A-Za-z0-9._-]+)/edit/state/$', views_edit.change_state, name='wg_change_state'),
url(r'^(?P<name>[A-Za-z0-9._-]+)/edit/info/$', views_edit.edit_info, name='wg_edit_info'),
url(r'^(?P<name>[A-Za-z0-9._-]+)/edit/conclude/$', views_edit.conclude, name='wg_conclude'),
url(r'^(?P<name>[A-Za-z0-9._-]+)/edit/addcomment/$', views_edit.add_comment, name='rec_add_comment'),
url(r'^(?P<name>[A-Za-z0-9._-]+)/edit/(?P<ann>action|review)/$', views_ballot.announcement_text, name='rec_announcement_text'),
url(r'^(?P<name>[A-Za-z0-9._-]+)/edit/position/$', views_ballot.edit_position, name='rec_edit_position'),
url(r'^(?P<name>[A-Za-z0-9._-]+)/edit/sendballotcomment/$', views_ballot.send_ballot_comment, name='rec_send_ballot_comment'),
url(r'^(?P<name>[A-Za-z0-9._-]+)/edit/approveballot/$', views_ballot.approve_ballot, name='rec_approve_ballot'),
url(r'^(?P<name>[A-Za-z0-9._-]+)/edit/addcomment/$', views_edit.add_comment, name='wg_add_comment'),
url(r'^(?P<name>[A-Za-z0-9._-]+)/edit/(?P<ann>action|review)/$', views_ballot.announcement_text, name='wg_announcement_text'),
url(r'^(?P<name>[A-Za-z0-9._-]+)/edit/position/$', views_ballot.edit_position, name='wg_edit_position'),
url(r'^(?P<name>[A-Za-z0-9._-]+)/edit/sendballotcomment/$', views_ballot.send_ballot_comment, name='wg_send_ballot_comment'),
url(r'^(?P<name>[A-Za-z0-9._-]+)/edit/approveballot/$', views_ballot.approve_ballot, name='wg_approve_ballot'),
url(r'^(?P<name>[A-Za-z0-9._-]+)/submit/$', views_submit.submit, name='wg_submit'),
)

View file

@ -1,9 +1,28 @@
from django.conf import settings
import re
from redesign.group.models import GroupEvent
from datetime import datetime
from group.models import GroupEvent
from doc.models import Document
from ietf.utils.history import find_history_active_at
def set_or_create_charter(wg):
try:
charter = Document.objects.get(name="charter-ietf-" + wg.acronym)
except Document.DoesNotExist:
charter = Document.objects.create(
name="charter-ietf-%s" % wg.acronym,
time=datetime.now(),
type_id="charter",
title=wg.name,
group=wg,
abstract=wg.name,
rev="",
)
wg.charter = charter
wg.save()
return charter
def add_wg_comment(request, wg, text, ballot=None):
if request:
login = request.user.get_profile()
@ -29,6 +48,24 @@ def log_state_changed(request, doc, by, prev_state, note=''):
e.save()
return e
def log_group_state_changed(request, wg, by, note=''):
from group.models import GroupEvent
e = GroupEvent(group=wg, by=by)
if wg.state_id == "proposed":
e.type = "proposed"
elif wg.state_id == "active":
e.type = "started"
elif wg.state_id == "conclude":
e.type = "concluded"
e.desc = u"%s group" % e.type.capitalize()
if note:
e.desc += "<br>%s" % note
e.save()
return e
def log_info_changed(request, wg, by, type=None, note=''):
from group.models import GroupEvent

View file

@ -96,7 +96,7 @@ def edit_position(request, name):
except ObjectDoesNotExist:
wglist = GroupHistory.objects.filter(acronym=name)
if wglist:
return redirect('rec_edit_position', name=wglist[0].group.acronym)
return redirect('wg_edit_position', name=wglist[0].group.acronym)
else:
raise Http404
@ -193,7 +193,7 @@ def edit_position(request, name):
qstr = "?return_to_url=%s" % return_to_url
if request.GET.get('ad'):
qstr += "&ad=%s" % request.GET.get('ad')
return HttpResponseRedirect(urlreverse("rec_send_ballot_comment", kwargs=dict(name=wg.acronym)) + qstr)
return HttpResponseRedirect(urlreverse("wg_send_ballot_comment", kwargs=dict(name=wg.acronym)) + qstr)
else:
return HttpResponseRedirect(return_to_url)
else:
@ -226,7 +226,7 @@ def send_ballot_comment(request, name):
except ObjectDoesNotExist:
wglist = GroupHistory.objects.filter(acronym=name)
if wglist:
return redirect('rec_send_ballot_comment', name=wglist[0].group.acronym)
return redirect('wg_send_ballot_comment', name=wglist[0].group.acronym)
else:
raise Http404
@ -315,7 +315,7 @@ def announcement_text(request, name, ann):
except ObjectDoesNotExist:
wglist = GroupHistory.objects.filter(acronym=name)
if wglist:
return redirect('rec_announcement_text', name=wglist[0].group.acronym)
return redirect('wg_announcement_text', name=wglist[0].group.acronym)
else:
raise Http404
@ -349,7 +349,7 @@ def announcement_text(request, name, ann):
doc.time = e.time
doc.save()
return redirect('record_view', name=wg.acronym)
return redirect('wg_view_record', name=wg.acronym)
return render_to_response('wgrecord/announcement_text.html',
dict(doc=doc,
announcement=ann,
@ -366,7 +366,7 @@ def approve_ballot(request, name):
except ObjectDoesNotExist:
wglist = GroupHistory.objects.filter(acronym=name)
if wglist:
return redirect('rec_approve_ballot', name=wglist[0].group.acronym)
return redirect('wg_approve_ballot', name=wglist[0].group.acronym)
else:
raise Http404

View file

@ -9,7 +9,7 @@ from django import forms
from django.forms.util import ErrorList
from django.core.exceptions import ObjectDoesNotExist
from utils import log_state_changed, log_info_changed, update_telechat
from utils import log_state_changed, log_group_state_changed, log_info_changed, update_telechat, add_wg_comment, set_or_create_charter
from mails import email_secretariat
from ietf.ietfauth.decorators import group_required
from ietf.iesg.models import TelechatDates
@ -19,7 +19,6 @@ from name.models import CharterDocStateName, GroupStateName, GroupTypeName, DocT
from person.models import Person, Email
from group.models import Group, GroupEvent, GroupHistory, GroupURL, Role, RoleHistory, save_group_in_history
from utils import add_wg_comment
from views_search import json_emails
class ChangeStateForm(forms.Form):
@ -45,14 +44,14 @@ def change_state(request, name):
# Get WG by acronym, redirecting if there's a newer acronym
try:
wg = Group.objects.get(acronym=name)
charter = set_or_create_charter(wg)
except ObjectDoesNotExist:
wglist = GroupHistory.objects.filter(acronym=name)
if wglist:
return redirect('wg_change_state', name=wglist[0].group.acronym)
else:
raise Http404
# Get charter
charter = wg.charter if wg.charter else None
initial_review = charter.latest_event(InitialReviewDocEvent, type="initial_review")
login = request.user.get_profile()
@ -60,7 +59,7 @@ def change_state(request, name):
if request.method == 'POST':
form = ChangeStateForm(request.POST)
if form.is_valid():
if initial_review and form.cleaned_data['charter_state'].slug != "infrev" and initial_review.expires > datetime.now() and not form.cleaned_data['confirm_state']:
if charter.charter_state_id == "infrev" and initial_review and form.cleaned_data['charter_state'].slug != "infrev" and initial_review.expires > datetime.now() and not form.cleaned_data['confirm_state']:
form._errors['charter_state'] = "warning"
else:
state = form.cleaned_data['state']
@ -95,6 +94,8 @@ def change_state(request, name):
prev = wg.state
wg.state = state
ge = log_group_state_changed(request, wg, login, comment)
wg.save()
if change:
@ -115,7 +116,7 @@ def change_state(request, name):
e.desc = "IESG process started in state <b>%s</b>" % charter.charter_state.name
e.save()
if form.cleaned_data["initial_time"] != 0:
if form.cleaned_data["charter_state"].slug == "infrev" and form.cleaned_data["initial_time"] and form.cleaned_data["initial_time"] != 0:
e = InitialReviewDocEvent()
e.type = "initial_review"
e.by = login
@ -124,7 +125,7 @@ def change_state(request, name):
e.desc = "Initial review time expires %s" % e.expires.strftime("%Y-%m-%d")
e.save()
return redirect('record_view', name=wg.acronym)
return redirect('wg_view_record', name=wg.acronym)
else:
if wg.state_id != "proposed":
states = CharterDocStateName.objects.filter(slug__in=["infrev", "intrev", "extrev", "iesgrev", "approved"])
@ -212,6 +213,7 @@ def edit_info(request, name=None):
if request.path_info == reverse('wg_edit_info', kwargs={'name': name}):
# Editing. Get group
wg = get_object_or_404(Group, acronym=name)
charter = set_or_create_charter(wg)
new_wg = False
elif request.path_info == reverse('wg_create'):
wg = None
@ -219,14 +221,15 @@ def edit_info(request, name=None):
login = request.user.get_profile()
if wg and wg.charter:
e = wg.charter.latest_event(TelechatDocEvent, type="scheduled_for_telechat")
if not new_wg:
e = charter.latest_event(TelechatDocEvent, type="scheduled_for_telechat")
initial_telechat_date = e.telechat_date if e else None
else:
initial_telechat_date = None
if request.method == 'POST':
form = EditInfoForm(request.POST, initial=dict(telechat_date=initial_telechat_date))
if form.is_valid():
if (new_wg or form.cleaned_data['acronym'] != wg.acronym) and not_valid_acronym(form.cleaned_data['acronym']) and not form.cleaned_data['confirm_acronym']:
try:
@ -254,17 +257,9 @@ def edit_info(request, name=None):
e.save()
if not wg.charter:
# Create adjoined charter
try:
charter = Document.objects.get(name="charter-ietf-"+r["acronym"])
except ObjectDoesNotExist:
charter = Document(type=DocTypeName.objects.get(name="Charter"),
title=r["name"],
abstract=r["name"],
name="charter-ietf-" + r["acronym"],
)
charter.charter_state = CharterDocStateName.objects.get(slug="infrev")
charter.group = wg
charter.save()
charter = set_or_create_charter(wg)
charter.charter_state = CharterDocStateName.objects.get(slug="infrev")
charter.save()
e = DocEvent(doc=charter, type="started_iesg_process")
e.time = datetime.now()
@ -340,7 +335,7 @@ def edit_info(request, name=None):
attr = attr_role[0]
rname = attr_role[1]
new = get_sorted_string(attr, ",")
old = map(lambda x: x.email.address, wg.role_set.filter(name__name=rname).order_by('email__address'))
old = [x.email.address for x in wg.role_set.filter(name__name=rname).order_by('email__address')]
if new != old:
# Remove old roles and save them in history
for role in wg.role_set.filter(name__name=rname):
@ -354,7 +349,7 @@ def edit_info(request, name=None):
# update urls
new_urls = get_sorted_string('urls', '\n')
old_urls = map(lambda x: x.url + " (" + x.name + ")", wg.groupurl_set.order_by('url'))
old_urls = [x.url + " (" + x.name + ")" for x in wg.groupurl_set.order_by('url')]
if new_urls != old_urls:
# Remove old urls
for u in wg.groupurl_set.all():
@ -377,21 +372,21 @@ def edit_info(request, name=None):
if new_wg:
return redirect('wg_change_state', name=wg.acronym)
else:
return redirect('record_view', name=wg.acronym)
return redirect('wg_view_record', name=wg.acronym)
else:
if wg:
init = dict(name=wg.name if wg.name else None,
if not new_wg:
init = dict(name=wg.name,
acronym=wg.acronym,
chairs=json_emails(map(lambda x: x.email, wg.role_set.filter(name="Chair"))),
secretaries=json_emails(map(lambda x: x.email, wg.role_set.filter(name="Secr"))),
techadv=json_emails(map(lambda x: x.email, wg.role_set.filter(name="Techadv"))),
chairs=json_emails([x.email for x in wg.role_set.filter(name="Chair")]),
secretaries=json_emails([x.email for x in wg.role_set.filter(name="Secr")]),
techadv=json_emails([x.email for x in wg.role_set.filter(name="Techadv")]),
charter=wg.charter.name if wg.charter else None,
ad=wg.ad.id if wg.ad else None,
parent=wg.parent.id if wg.parent else None,
list_email=wg.list_email if wg.list_email else None,
list_subscribe=wg.list_subscribe if wg.list_subscribe else None,
list_archive=wg.list_archive if wg.list_archive else None,
urls=string.join(map(lambda x: x.url + " (" + x.name + ")", wg.groupurl_set.all()), "\n"),
urls=string.join([x.url + " (" + x.name + ")" for x in wg.groupurl_set.all()], "\n"),
comments=wg.comments if wg.comments else None,
telechat_date=initial_telechat_date,
)
@ -408,7 +403,7 @@ def edit_info(request, name=None):
context_instance=RequestContext(request))
class ConcludeForm(forms.Form):
comment = forms.CharField(widget=forms.Textarea, label="Instructions", required=False)
instructions = forms.CharField(widget=forms.Textarea, required=True)
@group_required('Area_Director','Secretariat')
def conclude(request, name):
@ -427,15 +422,11 @@ def conclude(request, name):
if request.method == 'POST':
form = ConcludeForm(request.POST)
if form.is_valid():
comment = form.cleaned_data['comment']
save_group_in_history(wg)
wg.state = GroupStateName.objects.get(name="Concluded")
wg.save()
instructions = form.cleaned_data['instructions']
email_secretariat(request, wg, "conclude", comment)
email_secretariat(request, wg, "conclude", instructions)
return redirect('record_view', name=wg.acronym)
return redirect('wg_view_record', name=wg.acronym)
else:
form = ConcludeForm()
@ -463,7 +454,7 @@ def add_comment(request, name):
#email_owner(request, doc, doc.ad, login,
# "A new comment added by %s" % login.name)
return redirect('record_view', name=wg.acronym)
return redirect('wg_view_record', name=wg.acronym)
else:
form = AddCommentForm()

View file

@ -35,7 +35,7 @@ def _get_html(key, filename):
return content
@decorator_from_middleware(GZipMiddleware)
def record_main(request, name, rev, tab):
def wg_main(request, name, rev, tab):
if tab is None:
tab = "charter"
try:
@ -43,10 +43,13 @@ def record_main(request, name, rev, tab):
except ObjectDoesNotExist:
wglist = GroupHistory.objects.filter(acronym=name)
if wglist:
return redirect('record_view', name=wglist[0].group.acronym)
return redirect('wg_view_record', name=wglist[0].group.acronym)
else:
raise Http404
if not wg.charter:
create_empty_charter(wg)
if rev != None:
charter = get_charter_for_revision(wg.charter, rev)
gh = get_group_for_revision(wg, rev)
@ -56,23 +59,23 @@ def record_main(request, name, rev, tab):
info = {}
info['prev_acronyms'] = list(set(map(lambda x: x.acronym, wg.history_set.exclude(acronym=wg.acronym))))
prev_list_email = list(set(map(lambda x: x.list_email, wg.history_set.exclude(list_email=wg.list_email))))
info['prev_acronyms'] = list(set([x.acronym for x in wg.history_set.exclude(acronym=wg.acronym)]))
prev_list_email = list(set([x.list_email for x in wg.history_set.exclude(list_email=wg.list_email)]))
if prev_list_email != [u'']:
info['prev_list_email'] = prev_list_email
prev_list_subscribe = list(set(map(lambda x: x.list_email, wg.history_set.exclude(list_subscribe=wg.list_subscribe))))
prev_list_subscribe = list(set([x.list_email for x in wg.history_set.exclude(list_subscribe=wg.list_subscribe)]))
if prev_list_subscribe != [u'']:
info['prev_list_subscribe'] = prev_list_subscribe
prev_list_archive = list(set(map(lambda x: x.list_archive, wg.history_set.exclude(list_archive=wg.list_archive))))
prev_list_archive = list(set([x.list_archive for x in wg.history_set.exclude(list_archive=wg.list_archive)]))
if prev_list_archive != [u'']:
info['prev_list_archive'] = prev_list_archive
info['chairs'] = map(lambda x: x.email.person.name, wg.role_set.filter(name__slug="chair"))
info['chairs'] = [x.email.person.name for x in wg.role_set.filter(name__slug="chair")]
if hasattr(gh, 'rolehistory_set'):
info['history_chairs'] = map(lambda x: x.email.person.name, gh.rolehistory_set.filter(name__slug="chair"))
info['history_chairs'] = [x.email.person.name for x in gh.rolehistory_set.filter(name__slug="chair")]
else:
info['history_chairs'] = map(lambda x: x.email.person.name, gh.role_set.filter(name__slug="chair"))
info['secr'] = map(lambda x: x.email.person.name, wg.role_set.filter(name__slug="secr"))
info['techadv'] = map(lambda x: x.email.person.name, wg.role_set.filter(name__slug="techadv"))
info['history_chairs'] = [x.email.person.name for x in gh.role_set.filter(name__slug="chair")]
info['secr'] = [x.email.person.name for x in wg.role_set.filter(name__slug="secr")]
info['techadv'] = [x.email.person.name for x in wg.role_set.filter(name__slug="techadv")]
if charter:
content = _get_html(
@ -109,7 +112,8 @@ def record_main(request, name, rev, tab):
versions = _get_versions(wg.charter) # Important: wg.charter not charter
history = _get_history(wg)
info['last_update'] = history[0]['date']
if history:
info['last_update'] = history[0]['date']
charter_text_url = charter.get_txt_url()
@ -181,13 +185,13 @@ def _get_versions(charter, include_replaced=True):
ov.append({"name": charter.name, "rev": charter.rev, "date":charter.time})
return ov
def record_ballot(request, name):
def wg_ballot(request, name):
try:
wg = Group.objects.get(acronym=name)
except ObjectDoesNotExist:
wglist = GroupHistory.objects.filter(acronym=name)
if wglist:
return redirect('record_view', name=wglist[0].group.acronym)
return redirect('wg_view_record', name=wglist[0].group.acronym)
else:
raise Http404
@ -203,7 +207,7 @@ def record_ballot(request, name):
latest_positions = []
no_record = []
for p in active_ads:
p_pos = list(GroupBallotPositionDocEvent.objects.filter(doc=doc, ad=p).order_by("-time"))
p_pos = list(GroupBallotPositionDocEvent.objects.filter(doc=wg.charter, ad=p).order_by("-time"))
if p_pos != []:
latest_positions.append(p_pos[0])
else:

View file

@ -101,27 +101,31 @@ def search_query(query_original, sort_by=None):
elif by == "area":
results = results.filter(parent=query["area"])
elif by == "anyfield":
q_objs = []
q_objs.append(Q(name__icontains=query['anyfield']))
q_objs.append(Q(acronym__icontains=query['anyfield']))
q_objs.append(Q(state__name__icontains=query['anyfield']))
q_objs.append(Q(charter__charter_state__name__icontains=query['anyfield']))
q_objs.append(Q(ad__name__icontains=query['anyfield']))
q_objs.append(Q(parent__name__icontains=query['anyfield']))
q_objs.append(Q(history_set__acronym__icontains=query['anyfield']))
results = list(results.filter(reduce(lambda x, y: x | y, q_objs)))
q_objs = Q()
q_objs |= Q(acronym__icontains=query['anyfield'])
q_objs |= Q(state__name__icontains=query['anyfield'])
q_objs |= Q(charter__charter_state__name__icontains=query['anyfield'])
q_objs |= Q(ad__name__icontains=query['anyfield'])
q_objs |= Q(parent__name__icontains=query['anyfield'])
q_objs |= Q(history_set__acronym__icontains=query['anyfield'])
results = list(results.filter(*q_objs))
# Search charter texts
m = re.compile(query['anyfield'], re.IGNORECASE)
for g in Group.objects.filter(type="wg"):
if query['name']:
file_set = Group.objects.filter(type="wg", name__icontains=query["name"])
else:
file_set = Group.objects.filter(type="wg")
for g in file_set:
charter = g.charter
try:
file = open(os.path.join(charter.get_file_path(), charter.name+"-"+charter.rev+".txt"))
for line in file:
if m.search(line):
results.append(g)
break
except IOError:
pass # Pass silently for files not found
if charter:
try:
file = open(os.path.join(charter.get_file_path(), charter.name+"-"+charter.rev+".txt"))
for line in file:
if m.search(line):
results.append(g)
break
except IOError:
pass # Pass silently for files not found
elif by == "eacronym":
results = results.filter(history_set__acronym__icontains=query["eacronym"]).distinct()
@ -192,7 +196,7 @@ def search_results(request):
return render_to_response('wgrecord/search_results.html', {'recs':results, 'meta':meta}, context_instance=RequestContext(request))
elif len(results)==1:
wg = results[0]
return redirect('record_view', name=wg.acronym)
return redirect('wg_view_record', name=wg.acronym)
else:
return render_to_response('wgrecord/search_main.html', {'form':form, 'recs':results,'meta':meta}, context_instance=RequestContext(request))

View file

@ -8,20 +8,18 @@ from django.shortcuts import render_to_response, get_object_or_404, redirect
from django.core.urlresolvers import reverse
from django.template import RequestContext
from ietf.ietfauth.decorators import group_required
from django.core.exceptions import ObjectDoesNotExist
from group.models import save_group_in_history
from doc.models import Document, DocHistory, DocEvent, save_document_in_history
from redesign.group.models import Group
from django.conf import settings
from utils import next_revision
from utils import next_revision, set_or_create_charter
class UploadForm(forms.Form):
txt = forms.FileField(label=".txt format", required=True)
def __init__(self, *args, **kwargs):
super(UploadForm, self).__init__(*args, **kwargs)
def save(self, wg):
for ext in ['txt']:
fd = self.cleaned_data[ext]
@ -33,6 +31,7 @@ class UploadForm(forms.Form):
destination.write(chunk)
destination.close()
@group_required('Area_Director','Secretariat')
def submit(request, name):
# Get WG by acronym, redirecting if there's a newer acronym
try:
@ -44,7 +43,7 @@ def submit(request, name):
else:
raise Http404
# Get charter
charter = wg.charter if wg.charter else None
charter = set_or_create_charter(wg)
login = request.user.get_profile()
@ -70,7 +69,7 @@ def submit(request, name):
charter.time = datetime.now()
charter.save()
return HttpResponseRedirect(reverse('record_view', kwargs={'name': wg.acronym}))
return HttpResponseRedirect(reverse('wg_view_record', kwargs={'name': wg.acronym}))
else:
form = UploadForm()
return render_to_response('wgrecord/submit.html',

View file

@ -54,7 +54,7 @@ class DocumentInfo(models.Model):
raise NotImplemented
def get_txt_url(self):
if self.type.slug == "charter":
if self.type_id == "charter":
return "http://www.ietf.org/charters/"
else:
raise NotImplemented
@ -97,7 +97,7 @@ class Document(DocumentInfo):
def get_absolute_url(self):
name = self.name
if self.type.slug == "charter":
if self.type_id == "charter":
return urlreverse('record_view', kwargs={ 'name': self.group.acronym })
else:
if self.state == "rfc":

View file

@ -75,7 +75,7 @@ function editBallot(editPositionUrl) {
window.open(editPositionUrl);
}
function showRecBallot(acronym, editPositionUrl) {
function showWGBallot(acronym, editPositionUrl) {
var handleEditPosition = function() {
IETF.ballotDialog.hide();
window.location = IETF.editPositionUrl;
@ -87,7 +87,7 @@ function showRecBallot(acronym, editPositionUrl) {
if (!IETF.ballotDialog) {
el = document.createElement("div");
el.innerHTML = '<div id="ballot_dialog" style="visibility:hidden;"><div class="hd">Positions for <span id="ballot_dialog_name">draft-ietf-foo-bar</span></span></div><div class="bd"> <div id="ballot_dialog_body" style="overflow-y:scroll; height:400px;"></div> </div></div>';
el.innerHTML = '<div id="ballot_dialog" style="visibility:hidden;"><div class="hd">Positions for <span id="ballot_dialog_name">wgacronym</span></span></div><div class="bd"> <div id="ballot_dialog_body" style="overflow-y:scroll; height:400px;"></div> </div></div>';
document.getElementById("ietf-extras").appendChild(el);
var buttons = [{text:"Close", handler:handleClose, isDefault:true}];
@ -116,7 +116,7 @@ function showRecBallot(acronym, editPositionUrl) {
argument: null
}, null);
}
function editRecBallot(editPositionUrl) {
function editWGBallot(editPositionUrl) {
window.open(editPositionUrl);
}

View file

@ -5,6 +5,7 @@ jQuery(document).ready(function () {
}
function setMessageDraft(state) {
if (jQuery("#id_state").val() != "conclude") {
if (message[state]) {
if (state == "infrev") {
initial_time.show();
@ -17,6 +18,9 @@ jQuery(document).ready(function () {
} else {
jQuery("#id_message").val("");
}
} else {
jQuery("#id_message").val("");
}
}
jQuery("#id_charter_state").click(function (e) {
@ -24,4 +28,5 @@ jQuery(document).ready(function () {
});
jQuery("#id_charter_state").click();
});