Remove wgrecord after rename
- Legacy-Id: 3433
This commit is contained in:
parent
c631930b93
commit
a1a3949a4d
|
@ -1,36 +0,0 @@
|
|||
{% extends "base.html" %}
|
||||
{% comment %}
|
||||
Copyright The IETF Trust 2011, All Rights Reserved
|
||||
{% endcomment %}
|
||||
|
||||
{% block title %}Add comment on {{ wg.acronym }}{% endblock %}
|
||||
|
||||
{% block morecss %}
|
||||
form.add-comment #id_comment {
|
||||
width: 600px;
|
||||
height: 300px;
|
||||
}
|
||||
|
||||
form.add-comment .actions {
|
||||
padding-top: 20px;
|
||||
}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h1>Add comment on {{ wg.acronym }}</h1>
|
||||
|
||||
<p>The comment will be added to the history trail.</p>
|
||||
|
||||
<form class="add-comment" action="" method="POST">
|
||||
<table>
|
||||
{{ form.as_table }}
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="actions">
|
||||
<a href="{% url wg_view_record name=wg.acronym %}">Back</a>
|
||||
<input type="submit" value="Add comment"/>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
{% endblock %}
|
|
@ -1,25 +0,0 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}WG {{ announcement }} announcement writeup for {{ charter.chartered_group.acronym }}{% endblock %}
|
||||
|
||||
{% block morecss %}
|
||||
form #id_announcement_text {
|
||||
width: 700px;
|
||||
height: 600px;
|
||||
}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h1>WG {{ announcement }} announcement writeup for {{ charter.chartered_group.acronym }}</h1>
|
||||
|
||||
<form action="" method="POST">
|
||||
|
||||
{{ announcement_text_form.announcement_text }}
|
||||
|
||||
<div class="actions">
|
||||
<a href="{{ back_url }}">Back</a>
|
||||
<input type="submit" value="Save WG {{ announcement }} announcement text" />
|
||||
</div>
|
||||
</form>
|
||||
|
||||
{% endblock%}
|
|
@ -1,37 +0,0 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}Approve ballot for {{ wg.acronym }}{% endblock %}
|
||||
|
||||
{% block morecss %}
|
||||
form.approve-ballot pre {
|
||||
margin: 0;
|
||||
padding: 4px;
|
||||
border-top: 4px solid #eee;
|
||||
border-bottom: 4px solid #eee;
|
||||
}
|
||||
form.approve-ballot .announcement {
|
||||
overflow-x: auto;
|
||||
overflow-y: scroll;
|
||||
width: 800px;
|
||||
height: 400px;
|
||||
border: 1px solid #bbb;
|
||||
}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h1>Approve Ballot for {{ wg.acronym }}</h1>
|
||||
|
||||
<div>IETF announcement:</div>
|
||||
|
||||
<form class="approve-ballot" action="" method="POST">
|
||||
|
||||
<div class="announcement">
|
||||
<pre>{{ announcement }}</pre>
|
||||
</div>
|
||||
|
||||
<div class="actions">
|
||||
<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>
|
||||
{% endblock %}
|
|
@ -1,25 +0,0 @@
|
|||
{% autoescape off %}{{ ad }} has entered the following ballot position for
|
||||
{{ charter.name }}-{{ charter.rev }}: {{ pos.name }}
|
||||
|
||||
When responding, please keep the subject line intact and reply to all
|
||||
email addresses included in the To and CC lines. (Feel free to cut this
|
||||
introductory paragraph, however.)
|
||||
|
||||
{% if not block_comment and not comment %}
|
||||
There is no BLOCK or COMMENT text associated with this position.
|
||||
{% endif %}
|
||||
|
||||
{% if block_comment %}----------------------------------------------------------------------
|
||||
BLOCK:
|
||||
----------------------------------------------------------------------
|
||||
|
||||
{{ block_comment|safe|wordwrap:73 }}
|
||||
|
||||
|
||||
{% endif %}{% if comment %}----------------------------------------------------------------------
|
||||
COMMENT:
|
||||
----------------------------------------------------------------------
|
||||
|
||||
{{ comment|safe|wordwrap:73 }}
|
||||
{% endif %}
|
||||
{% endautoescape %}
|
|
@ -1,29 +0,0 @@
|
|||
{% extends "base.html" %}
|
||||
{% comment %}
|
||||
Copyright The IETF Trust 2011, All Rights Reserved
|
||||
{% endcomment %}
|
||||
|
||||
{% block title %}Working Groups for {{ ad_name }}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h1>Working Groups for {{ ad_name }}</h1>
|
||||
|
||||
<p>
|
||||
<span id="create_wg" class="yui-button yui-link-button" style="margin-left:2px;"><span class="first-child"><a href="/wgrecord/create/">Create WG</a></span></span>
|
||||
</p>
|
||||
|
||||
{% if not recs %}
|
||||
<p><b>No WGs match your query.</b></p>
|
||||
{% else %}
|
||||
<table class="ietf-table ietf-doctable">
|
||||
<tr>
|
||||
{% for hdr in meta.hdrs %}
|
||||
{% include "wgrecord/table_header.html" %}
|
||||
{% endfor %}
|
||||
</tr>
|
||||
{% for wg in recs %}
|
||||
{% include "wgrecord/search_result_row.html" %}
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% endif %}
|
||||
{% endblock content %}
|
|
@ -1,121 +0,0 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}
|
||||
{% ifequal option "initcharter" %}
|
||||
Initiate chartering of WG {{ wg.acronym }}
|
||||
{% else %}
|
||||
{% ifequal option "recharter" %}
|
||||
Recharter WG {{ wg.acronym }}
|
||||
{% else %}
|
||||
{% ifequal option "abandon" %}
|
||||
Abandon effort on WG {{ wg.acronym }}
|
||||
{% else %}
|
||||
Change state of WG {{ wg.acronym }}
|
||||
{% endifequal %}
|
||||
{% endifequal %}
|
||||
{% endifequal %}
|
||||
{% endblock %}
|
||||
|
||||
{% block morecss %}
|
||||
form.change-state select {
|
||||
width: 22em;
|
||||
}
|
||||
|
||||
#id_message, #id_comment {
|
||||
width: 40em;
|
||||
}
|
||||
|
||||
form.change-state .actions {
|
||||
text-align: right;
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h1>{% ifequal option "initcharter" %}
|
||||
Initiate chartering of WG {{ wg.acronym }}
|
||||
{% else %}
|
||||
{% ifequal option "recharter" %}
|
||||
Recharter WG {{ wg.acronym }}
|
||||
{% else %}
|
||||
{% ifequal option "abandon" %}
|
||||
Abandon effort on WG {{ wg.acronym }}
|
||||
{% else %}
|
||||
Change state of WG {{ wg.acronym }}
|
||||
{% endifequal %}
|
||||
{% endifequal %}
|
||||
{% endifequal %}
|
||||
</h1>
|
||||
|
||||
{% ifnotequal option "initcharter" %}{% ifnotequal option "recharter" %}{% ifnotequal option "abandon" %}<p class="helptext">For help on the states, see the <a href="{% url help_charter_states %}">state table</a>.</p>{% endifnotequal %}{% endifnotequal %}{% endifnotequal %}
|
||||
|
||||
<form class="change-state" action="" method="post">
|
||||
<table>
|
||||
{% for field in form.visible_fields %}
|
||||
<tr>
|
||||
{% ifequal field.name "initial_time" %}
|
||||
{% ifequal option "recharter" %}
|
||||
<th>{{ field.label_tag }}:</th>
|
||||
<td>{{ field }}
|
||||
{% if field.help_text %}<div class="help">{{ field.help_text }}</div>{% endif %}
|
||||
{% else %}
|
||||
{% ifequal option "initcharter" %}
|
||||
<th>{{ field.label_tag }}:</th>
|
||||
<td>{{ field }}
|
||||
{% if field.help_text %}<div class="help">{{ field.help_text }}</div>{% endif %}
|
||||
{% endifequal %}
|
||||
{% endifequal %}
|
||||
{% else %}
|
||||
<th>{{ field.label_tag }}:</th>
|
||||
<td>{{ field }}
|
||||
{% if field.help_text %}<div class="help">{{ field.help_text }}</div>{% endif %}
|
||||
{% endifequal %}
|
||||
{% ifequal field.name "charter_state" %}
|
||||
{% ifequal field.errors "warning" %}
|
||||
<ul><li>The initial review time hasn't elapsed. Select this checkbox to proceed anyway: <label><input type="checkbox" name="confirm_state" /></label></li></ul>
|
||||
{% endifequal %}
|
||||
{% endifequal %}
|
||||
{% ifnotequal field.name "charter_state" %}
|
||||
{{ field.errors }}
|
||||
{% endifnotequal %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
<tr>
|
||||
<td colspan="2" class="actions">
|
||||
{% if option %}
|
||||
<input type="submit" value="Submit"/>
|
||||
{% else %}
|
||||
<a href="{% url wg_view_record name=wg.acronym %}">Back</a>
|
||||
<input type="submit" value="Save"/>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
|
||||
{% if prev_state %}
|
||||
<h3>Or revert to previous state</h3>
|
||||
|
||||
<div class="prev-state">
|
||||
<form action="" method="post">
|
||||
<input type="hidden" name="charter_state" value="{{ prev_charter_state.slug }}" />
|
||||
<input type="hidden" name="state" value="{{ prev_state.slug }}" />
|
||||
<input type="submit" value="Back to {{ prev_charter_state.name }}" />
|
||||
</form>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block content_end %}
|
||||
<script type="text/javascript">
|
||||
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: "
|
||||
};
|
||||
|
||||
</script>
|
||||
<script type="text/javascript" src="/js/wg-change-state.js"></script>
|
||||
{% endblock %}
|
|
@ -1,34 +0,0 @@
|
|||
<div class="ietf-box diffTool">
|
||||
<h2 style="margin-top:0;margin-bottom:4px;">Diffs</h2>
|
||||
<form action="http{% if request.is_secure %}s{% endif %}://tools.ietf.org/rfcdiff" method="get" target="_blank" style="margin:0;">
|
||||
<table>
|
||||
<tr><td>
|
||||
<label>From:</label> <select name="url1">
|
||||
{% for c in versions %}
|
||||
<option value="{{ charter_text_url }}{{c.name}}-{{c.rev}}.txt" {% ifequal forloop.counter 2 %} selected="selected" {% endifequal %}>{{c.name}}-{{c.rev}} ({{c.date}})</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</td>
|
||||
<td rowspan="2" valign="top">
|
||||
Format:
|
||||
<select name="difftype">
|
||||
<option value="--html" selected="selected">Side-by-side</option>
|
||||
<option value="--abdiff">Before-after</option>
|
||||
<option value="--chbars">Change bars</option>
|
||||
<option value="--hwdiff">Wdiff</option>
|
||||
</select> <input name="submit" value="Go!" type="submit" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label>To:</label>
|
||||
<select name="url2">
|
||||
{% for c in versions %}
|
||||
<option value="{{ charter_text_url }}{{c.name}}-{{c.rev}}.txt" {% ifequal forloop.counter 1 %} selected="selected" {% endifequal %}>{{c.name}}-{{c.rev}} ({{c.date}})</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
</div>
|
|
@ -1,38 +0,0 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}Request closing of WG {{ wg.acronym }}{% endblock %}
|
||||
|
||||
{% block morecss %}
|
||||
#id_instructions {
|
||||
width: 40em;
|
||||
}
|
||||
|
||||
form.conclude .actions {
|
||||
text-align: right;
|
||||
padding-top: 10px;
|
||||
}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h1>Request closing of {{ wg.acronym }}</h1>
|
||||
|
||||
<p>
|
||||
Please provide instructions regarding the disposition of each
|
||||
active Internet-Draft (such as to withdraw the draft, move it to
|
||||
another WG, convert it to an individual submission, and so on),
|
||||
wording for the closure announcement, and the status of the WG
|
||||
mailing list (will it remain open or should it be closed).
|
||||
</p>
|
||||
<form class="conclude" action="" method="post">
|
||||
<table>
|
||||
{{ form.as_table }}
|
||||
<tr>
|
||||
<td colspan="2" class="actions">
|
||||
<a href="{% url wg_view_record name=wg.acronym %}">Back</a>
|
||||
<input type="submit" value="Send request"/>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
|
||||
{% endblock %}
|
|
@ -1,5 +0,0 @@
|
|||
{% comment %}
|
||||
Copyright The IETF Trust 2011, All Rights Reserved
|
||||
{% endcomment %}
|
||||
{% load ietf_filters %}<td class="date">{{ wg.time|date:"Y-m-d" }}
|
||||
</td>
|
|
@ -1,102 +0,0 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}
|
||||
{% if wg %}
|
||||
Edit info on {{ wg.acronym }}
|
||||
{% else %}
|
||||
Create WG
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block morecss %}
|
||||
form.edit-info #id_name {
|
||||
width: 396px;
|
||||
}
|
||||
|
||||
form.edit-info #id_list_email {
|
||||
width: 396px;
|
||||
}
|
||||
|
||||
form.edit-info #id_list_subscribe {
|
||||
width: 396px;
|
||||
}
|
||||
|
||||
form.edit-info #id_list_archive {
|
||||
width: 396px;
|
||||
}
|
||||
|
||||
form.edit-info #id_urls {
|
||||
width: 400px;
|
||||
}
|
||||
|
||||
form.edit-info #id_comments {
|
||||
width: 400px;
|
||||
}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block pagehead %}
|
||||
<link rel="stylesheet" type="text/css" href="/css/token-input.css"></link>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{% load ietf_filters %}
|
||||
<h1>{% if wg %}
|
||||
Edit info on {{ wg.acronym }}
|
||||
{% else %}
|
||||
Create WG record
|
||||
{% endif %}
|
||||
</h1>
|
||||
|
||||
<form class="edit-info" action="" method="POST">
|
||||
<table>
|
||||
{% for field in form.visible_fields %}
|
||||
<tr>
|
||||
<th>{{ field.label_tag }}:</th>
|
||||
<td>{{ field }}
|
||||
{% ifequal field.name "ad" %}
|
||||
{% if user|in_group:"Area_Director" %}
|
||||
<label><input type="checkbox" name="ad" value="{{ login.pk }}" /> Assign to me</label>
|
||||
{% endif %}
|
||||
{% endifequal %}
|
||||
{% if field.help_text %}<div class="help">{{ field.help_text }}</div>{% endif %}
|
||||
{{ field.errors }}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="actions">
|
||||
{% if wg %}
|
||||
<a href="{% url wg_view_record name=wg.acronym %}">Back</a>
|
||||
<input type="submit" value="Save"/>
|
||||
{% else %}
|
||||
<input type="submit" value="Create"/>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
$(document).ready(function () {
|
||||
var chairs = eval($("#id_chairs").val()),
|
||||
secretaries = eval($("#id_secretaries").val()),
|
||||
techadv = eval($("#id_techadv").val());
|
||||
$("#id_chairs").tokenInput("/wgrecord/searchPerson/", { hintText: "",
|
||||
preventDuplicates: true,
|
||||
prePopulate: chairs });
|
||||
$("#id_secretaries").tokenInput("/wgrecord/searchPerson/", { hintText: "",
|
||||
preventDuplicates: true,
|
||||
prePopulate: secretaries });
|
||||
$("#id_techadv").tokenInput("/wgrecord/searchPerson/", { hintText: "",
|
||||
preventDuplicates: true,
|
||||
prePopulate: techadv });
|
||||
$("#id_name").focus();
|
||||
});
|
||||
{% endblock %}
|
||||
|
||||
{% block content_end %}
|
||||
<script type="text/javascript" src="/js/lib/jquery.tokeninput.js"></script>
|
||||
{% endblock %}
|
|
@ -1,71 +0,0 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}Change position for {{ ad.name }} on {{ wg.acronym }}{% endblock %}
|
||||
|
||||
{% block morecss %}
|
||||
form.position-form .position ul {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
form.position-form .position li {
|
||||
list-style-type: none;
|
||||
float: left;
|
||||
padding-right: 10px;
|
||||
}
|
||||
form.position-form .last-edited {
|
||||
font-style: italic;
|
||||
}
|
||||
form.position-form .block_comment {
|
||||
padding-top: 20px
|
||||
}
|
||||
form.position-form #id_block_comment,
|
||||
form.position-form #id_comment {
|
||||
width: 700px;
|
||||
height: 250px;
|
||||
}
|
||||
form.position-form .comment {
|
||||
margin-top: 20px;
|
||||
}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h1>Change position for {{ ad.name }} on {{ wg.acronym }}</h1>
|
||||
|
||||
<form class="position-form" action="" method="POST">
|
||||
<div>
|
||||
<span class="position">{{ form.position }}</span>
|
||||
<span class="actions">
|
||||
<input type="submit" name="send_mail" value="Save and send email"/>
|
||||
<input type="submit" value="Save"/>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div style="clear:left"></div>
|
||||
|
||||
<div class="block_comment-widgets" {% ifnotequal form.position.initial "block" %}style="display:none"{% endifnotequal %}>
|
||||
<div class="block_comment">
|
||||
{{ form.block_comment.label_tag }}:
|
||||
{% if old_pos and old_pos.block_comment_time %}<span class="last-edited">(last edited {{ old_pos.block_comment_time }})</span>{% endif %}
|
||||
</div>
|
||||
{{ form.block_comment.errors }}
|
||||
{{ form.block_comment }}
|
||||
</div>
|
||||
|
||||
<div class="comment">
|
||||
{{ form.comment.label_tag }}:
|
||||
{% if old_pos and old_pos.comment_time %}<span class="last-edited">(last edited {{ old_pos.comment_time }}){% endif %}</span>
|
||||
</div>
|
||||
{{ form.comment }}
|
||||
|
||||
<div class="actions">
|
||||
<a href="{{ return_to_url }}">Back</a>
|
||||
</div>
|
||||
|
||||
{{ form.return_to_url }}
|
||||
|
||||
</form>
|
||||
{% endblock %}
|
||||
|
||||
{% block content_end %}
|
||||
<script type="text/javascript" src="/js/wg-edit-position.js"></script>
|
||||
{% endblock %}
|
|
@ -1,5 +0,0 @@
|
|||
{% autoescape off %}
|
||||
{{ text }}
|
||||
|
||||
WG Record URL: {{ url }}
|
||||
{% endautoescape %}
|
|
@ -1,29 +0,0 @@
|
|||
{% extends "base.html" %}
|
||||
{% comment %}
|
||||
Copyright The IETF Trust 2011, All Rights Reserved
|
||||
{% endcomment %}
|
||||
|
||||
{% block title %}Working Groups in IESG process{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h1>Working Groups in IESG process</h1>
|
||||
|
||||
<p>
|
||||
<span id="create_wg" class="yui-button yui-link-button" style="margin-left:2px;"><span class="first-child"><a href="/wgrecord/create/">Create WG</a></span></span>
|
||||
</p>
|
||||
|
||||
{% if not recs %}
|
||||
<p><b>No WGs match your query.</b></p>
|
||||
{% else %}
|
||||
<table class="ietf-table ietf-doctable">
|
||||
<tr>
|
||||
{% for hdr in meta.hdrs %}
|
||||
{% include "wgrecord/table_header.html" %}
|
||||
{% endfor %}
|
||||
</tr>
|
||||
{% for wg in recs %}
|
||||
{% include "wgrecord/search_result_row.html" %}
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% endif %}
|
||||
{% endblock content %}
|
|
@ -1,56 +0,0 @@
|
|||
{% comment %}
|
||||
Copyright The IETF Trust 2011, All Rights Reserved
|
||||
{% endcomment %}
|
||||
{% load ietf_filters %}
|
||||
<table class="ietf-ballot"><tr valign="top"><td class="left">
|
||||
|
||||
{% if user|in_group:"Area_Director,Secretariat" %}
|
||||
{% if user|in_group:"Area_Director" %}
|
||||
<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="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 %}
|
||||
|
||||
<p style="margin-top:1em;"><span class="square" style="background:#c00000;"></span><b>Blocking</b><br/>
|
||||
{% with info.pos_block as positions %}{% include "wgrecord/record_ballot_list.html" %}{% endwith %}</p>
|
||||
|
||||
<p><span class="square" style="background:#80ff80;"></span><b>Yes</b><br/>
|
||||
{% with info.pos_yes as positions %}{% include "wgrecord/record_ballot_list.html" %}{% endwith %}</p>
|
||||
|
||||
<p><span class="square" style="background:#80ff80;"></span><b>No</b><br/>
|
||||
{% with info.pos_no as positions %}{% include "wgrecord/record_ballot_list.html" %}{% endwith %}</p>
|
||||
|
||||
<p><span class="square" style="background:#ffff00;"></span><b>Abstain</b><br/>
|
||||
{% with info.pos_abstain as positions %}{% include "wgrecord/record_ballot_list.html" %}{% endwith %}</p>
|
||||
|
||||
<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 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 %}
|
||||
</p>
|
||||
|
||||
</td>
|
||||
<td class="right">
|
||||
|
||||
<h2 style="margin-top:12px;">Comments</h2>
|
||||
|
||||
{% for pos in info.positions %}
|
||||
{% if pos.comment or pos.block_comment %}
|
||||
<h2 class="ballot_ad"><a name="{{pos.ad|slugify}}">{{pos.ad|escape}}</a></h2>
|
||||
|
||||
{% if pos.block_comment %}
|
||||
<p><b>Blocking ({{pos.block_comment_time}})</b> <img src="/images/comment.png" width="14" height="12" alt=""/></p>
|
||||
<pre>{{pos.block_comment|fill:"80"|escape }}</pre>
|
||||
{% endif %}
|
||||
|
||||
{% if pos.comment %}
|
||||
<p><b>Comment ({{pos.comment_time}})</b> <img src="/images/comment.png" width="14" height="12" alt=""/></p>
|
||||
<pre>{{pos.comment|fill:"80"|escape }}</pre>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</td></tr></table>
|
|
@ -1,6 +0,0 @@
|
|||
{% load ietf_filters %}
|
||||
{% for p in positions %}
|
||||
<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.comment or p.block_comment %} <a href="#{{p.ad|slugify}}"><img src="/images/comment.png" width="14" height="12" alt="*" border="0"/></a>{% endif %}<br/>
|
||||
{% empty %}
|
||||
<i>none</i>
|
||||
{% endfor %}
|
|
@ -1,40 +0,0 @@
|
|||
{% comment %}
|
||||
Copyright The IETF Trust 2011, All Rights Reserved
|
||||
{% endcomment %}
|
||||
|
||||
{% load ietf_filters %}
|
||||
<table class="ietf-table">
|
||||
<tr><th class="comment_date">Date</th><th>Version</th><th>By</th><th>Text</th></tr>
|
||||
|
||||
{% for c in history %}
|
||||
<tr class="{% cycle oddrow,evenrow %}"{% if c.is_com %} id="history-{{c.comment.id }}"{% endif %}>
|
||||
<td class="comment_date">{{ c.date|date:"Y-m-d" }}</td>
|
||||
|
||||
{% if c.is_rev %}
|
||||
<td>{{ c.info.version }}</td>
|
||||
<td>(System)</td>
|
||||
<td>New version available: <a href="{{ c.txt_url }}charter-ietf-{{ c.group.acronym }}-{{c.charter.rev}}.txt">charter-ietf-{{ c.group.acronym }}-{{ c.charter.rev }}</a> {% if c.prev_charter %}(<a href="http://tools.ietf.org/rfcdiff?url1={{ c.txt_url }}charter-ietf-{{ c.group.acronym }}-{{c.charter.rev}}.txt&url2={{ c.txt_url }}charter-ietf-{{ c.prev_group.acronym }}-{{c.prev_charter.rev}}.txt">diff from -{{ c.prev_charter.rev }}</a>){% endif %}</td>
|
||||
{% endif %}
|
||||
|
||||
{% if c.is_com %}
|
||||
<td>{{ c.info.version }}</td>
|
||||
<td>{{ c.info.by|escape }}</td>
|
||||
<td>{% if c.comment.ballot %}
|
||||
[Ballot {{ c.comment.get_ballot_display }}]<br />
|
||||
{% endif %}
|
||||
{% if c.info.snipped %}
|
||||
<div id="commentS{{c.comment.id}}">{{ c.info.textSnippet|safe }}</div>
|
||||
<span class="comment_toggle" onclick="toggleComment({{c.comment.id}})" id="commentT{{c.comment.id}}">[show all]</span>
|
||||
<div id="commentF{{c.comment.id}}" style="display:none;">
|
||||
{{ c.info.text|fill:"80"|safe|linebreaksbr|keep_spacing|sanitize_html|safe }}
|
||||
</div>
|
||||
{% else %}
|
||||
{{ c.info.text|fill:"80"|safe|linebreaksbr|keep_spacing|sanitize_html|safe }}
|
||||
{% endif %}
|
||||
</td>
|
||||
{% endif %}
|
||||
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
||||
</table>
|
|
@ -1,72 +0,0 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% comment %}
|
||||
Copyright The IETF Trust 2011, All Rights Reserved
|
||||
{% endcomment %}
|
||||
|
||||
{% load ietf_filters %}
|
||||
{% block morecss %}
|
||||
.metabox { width: 99%; margin-top:8px; padding:4px; margin-bottom:1em; }
|
||||
#metatable { border: 0; border-spacing: 0; }
|
||||
#metatable tr { vertical-align:top ;}
|
||||
.comment_toggle { text-decoration: underline; color: blue; }
|
||||
.comment_date { white-space: nowrap; }
|
||||
|
||||
div.diffTool { padding: 8px 4px; margin: 8px 0;}
|
||||
.diffTool label { float:left; width:50px; }
|
||||
|
||||
.markup_draft pre {line-height: 1.2em; margin: 0; }
|
||||
.m_hdr, .m_ftr { color: #808080; }
|
||||
.m_ftr { border-bottom: 1px solid #a0a0a0; }
|
||||
.m_h { font-family: arial; font-weight:bold;}
|
||||
.ietf-concluded-bg {background-color: #F8F8D0; }
|
||||
.ietf-concluded-warning { background:red;color:white;padding:2px 2px;}
|
||||
.ietf-proposed-bg { }
|
||||
.ietf-proposed-warning { background:green;color:white;padding:2px 2px;}
|
||||
{% endblock %}
|
||||
|
||||
{% block pagehead %}
|
||||
<link rel="alternate" type="application/atom+xml" href="/feed/wgcomments/{{ wg.acronym }}/" />
|
||||
<meta name="description" content="{% include "wgrecord/wg_description.html" %}" />
|
||||
{% endblock %}
|
||||
|
||||
{% block title %}{% include "wgrecord/wg_title.html" %}{% endblock title %}
|
||||
|
||||
{% block content %}
|
||||
<h1>{% include "wgrecord/wg_title.html" %}
|
||||
{% ifequal wg.state_id "conclude" %}<br/><span class="ietf-concluded-warning">(concluded WG)</span>{% endifequal %}
|
||||
{% ifequal wg.state_id "proposed" %}<br/><span class="ietf-proposed-warning">(proposed WG)</span>{% endifequal %}
|
||||
</h1>
|
||||
|
||||
<div id="mytabs" class="yui-navset">
|
||||
<ul class="yui-nav">
|
||||
<li{% ifequal tab "charter" %} class="selected"{% endifequal %}><a href="/wgrecord/{{ wg.acronym }}"><em>WG {% if snapshot %}(snapshot){% endif %}</em></a></li>
|
||||
<li{% if wg.charter %}{% ifequal wg.charter.charter_state_id "iesgrev" %}{% ifequal tab "ballot" %} class="selected"{% endifequal %}{%else%} class="disabled"{%endifequal%}{% else %} class="disabled"{% endif %}{% if snapshot %} class="disabled"{% endif %}><a href="/wgrecord/{{ wg.acronym }}/ballot/"><em>IESG Review</em></a></li>
|
||||
<li{% if wg.charter %}{% ifequal wg.charter.charter_state_id "iesgrev" %}{% ifequal tab "writeup" %} class="selected"{% endifequal %}{%else%} class="disabled"{%endifequal%}{% else %} class="disabled"{% endif %}{% if snapshot %} class="disabled"{% endif %}><a href="/wgrecord/{{ wg.acronym }}/writeup/"><em>IESG Writeups</em></a></li>
|
||||
<li{% ifequal tab "history" %} class="selected"{% endifequal %}{% if snapshot %} class="disabled"{% endif %}><a href="/wgrecord/{{ wg.acronym }}/history/"><em>History</em></a></li>
|
||||
</ul>
|
||||
<div class="yui-content">
|
||||
|
||||
{% block tab_content %}{% endblock %}
|
||||
|
||||
</div> <!-- yui-content -->
|
||||
</div> <!-- mytabs -->
|
||||
|
||||
{% endblock content %}
|
||||
|
||||
{% block scripts %}
|
||||
function toggleComment(n) {
|
||||
var el = document.getElementById("commentF"+n);
|
||||
var el2 = document.getElementById("commentS"+n);
|
||||
var el3 = document.getElementById("commentT"+n);
|
||||
if (el.style.display == 'none') {
|
||||
el.style.display = 'block';
|
||||
el2.style.display = 'none';
|
||||
el3.innerHTML = ""; //[hide]";
|
||||
} else {
|
||||
el.style.display = 'none';
|
||||
el2.style.display= 'block';
|
||||
el3.innerHTML = "[show all]";
|
||||
}
|
||||
}
|
||||
{% endblock scripts %}
|
|
@ -1,11 +0,0 @@
|
|||
{% extends "wgrecord/record_main.html" %}
|
||||
{% comment %}
|
||||
Copyright The IETF Trust 2011, All Rights Reserved
|
||||
{% endcomment %}
|
||||
|
||||
{% load ietf_filters %}
|
||||
|
||||
{% block tab_content %}
|
||||
{% include "wgrecord/record_ballot.html" %}
|
||||
{% endblock tab_content %}
|
||||
|
|
@ -1,59 +0,0 @@
|
|||
{% extends "wgrecord/record_main.html" %}
|
||||
|
||||
{% comment %}
|
||||
Copyright The IETF Trust 2011, All Rights Reserved
|
||||
{% endcomment %}
|
||||
|
||||
{% load ietf_filters %}
|
||||
|
||||
{% block tab_content %}
|
||||
{% block record_revision %}{% endblock %}
|
||||
<div class="ietf-box metabox">
|
||||
<table id="metatable" width="100%">
|
||||
{% block record_metatable %}{% endblock %}
|
||||
</table>
|
||||
|
||||
<div style="padding-top:6px;padding-bottom:6px;padding-left:2px;">
|
||||
{% block record_metalinks %}{% endblock %}
|
||||
</div>
|
||||
|
||||
{% block record_metabuttons %}
|
||||
{% if user|in_group:"Area_Director,Secretariat" %}
|
||||
{% if not snapshot %}
|
||||
<div style="padding-bottom:2px;">
|
||||
{% ifnotequal wg.charter.charter_state_id "notrev" %}
|
||||
{% ifnotequal wg.charter.charter_state_id "approved" %}
|
||||
<span id="wg_edit_state_button" class="yui-button yui-link-button" style="margin-left:2px;"><span class="first-child"><a href="{% url wg_startstop_process name=wg.acronym option='abandon' %}">Abandon effort</a></span></span>
|
||||
<span id="wg_edit_state_button" class="yui-button yui-link-button" style="margin-left:2px;"><span class="first-child"><a href="{% url wg_change_state name=wg.acronym %}">Change state</a></span></span>
|
||||
{% ifnotequal wg.state_id "conclude" %}
|
||||
<span id="wg_edit_info_button" class="yui-button yui-link-button" style="margin-left:2px;"><span class="first-child"><a href="{% url wg_submit name=wg.acronym %}">Edit charter</a></span></span>
|
||||
{% endifnotequal %}
|
||||
{% else %}
|
||||
<span id="wg_edit_state_button" class="yui-button yui-link-button" style="margin-left:2px;"><span class="first-child"><a href="{% url wg_startstop_process name=wg.acronym option='recharter' %}">Recharter</a></span></span>
|
||||
{% endifnotequal %}
|
||||
{% else %}
|
||||
<span id="wg_edit_state_button" class="yui-button yui-link-button" style="margin-left:2px;"><span class="first-child"><a href="{% url wg_startstop_process name=wg.acronym option='recharter' %}">Recharter</a></span></span>
|
||||
{% endifnotequal %}
|
||||
|
||||
{% ifequal wg.state_id "active" %}{% ifequal wg.charter.charter_state_id "approved" %}
|
||||
<span id="wg_conclude_button" class="yui-button yui-link-button" style="margin-left:2px;"><span class="first-child"><a href="{% url wg_conclude name=wg.acronym %}">Conclude WG</a></span></span>
|
||||
{% endifequal %}{% endifequal %}
|
||||
|
||||
{% ifnotequal wg.state_id "conclude" %}
|
||||
<span id="wg_edit_info_button" class="yui-button yui-link-button" style="margin-left:2px;"><span class="first-child"><a href="{% url wg_edit_info name=wg.acronym %}">Edit WG</a></span></span>
|
||||
{% endifnotequal %}
|
||||
|
||||
|
||||
</div>
|
||||
{% endif %}{# if not snapshot #}
|
||||
{% endif %}{# if user in group #}
|
||||
{% endblock record_metabuttons%}
|
||||
</div> <!-- metabox -->
|
||||
|
||||
<div id="charterText">
|
||||
{% block charter_text %}{% endblock %}
|
||||
</div> <!-- charterText -->
|
||||
{% endblock tab_content %}
|
||||
|
||||
{% block content_end %}
|
||||
{% endblock content_end %}
|
|
@ -1,81 +0,0 @@
|
|||
{% extends "wgrecord/record_tab_base.html" %}
|
||||
|
||||
{% comment %}
|
||||
Copyright The IETF Trust 2011, All Rights Reserved
|
||||
{% endcomment %}
|
||||
|
||||
{% load ietf_filters %}
|
||||
|
||||
{% block record_revision %}
|
||||
Snapshots: {% for d in versions reversed %}{% ifequal active_rev d.rev %}<strong>{% endifequal %}{% ifequal rev d.rev %}{% else %}{% ifequal active_rev d.rev %}<a href="{% url wg_view_record name=wg.acronym %}">{% else %}<a href="{% url wg_view_record name=wg.acronym %}{{d.rev}}/">{% endifequal %}{% endifequal %}{{ d.rev }}{% ifequal rev d.rev %}{% else %}</a>{% endifequal %}{% ifequal active_rev d.rev %}</strong>{% endifequal %} {% endfor %}
|
||||
{% endblock %}
|
||||
|
||||
{% block record_metatable %}
|
||||
<tr><td style="width: 15em">WG name:</td><td>{% if not snapshot %}{{ wg.name }}{% else %} {{ gh.name }} {% endif %}</td></tr>
|
||||
<tr><td>WG acronym:</td><td>{% if not snapshot %}{{ wg.acronym }} {% if info.prev_acronyms %}(previous acronyms: {% for a in info.prev_acronyms %}{{ a }}{% if not forloop.last %}, {% endif %}{% endfor %}){% endif %}{% else %}{{ gh.acronym }}{% endif %}</td></tr>
|
||||
<tr><td>IETF area:</td><td>{% if not snapshot %}{{ wg.parent|default:"-" }}{% else %}{{ gh.parent|default:"-" }}{% endif %}</td></tr>
|
||||
|
||||
<tr><td colspan='2'><hr size='1' noshade /></td></tr>
|
||||
|
||||
<tr><td>WG chairs:</td><td>{% if not snapshot %}{% for n in info.chairs %}{{ n }}{% if not forloop.last %}, {% endif %}{% endfor %}{% else %}{% for n in info.history_chairs %}{{ n }}{% if not forloop.last %}, {% endif %}{% endfor %}{% endif %}</td></tr>
|
||||
{% if not snapshot %}
|
||||
<tr><td>WG secretaries:</td><td>{% for n in info.secr %}{{ n }}{% if not forloop.last %}, {% endif %}{% endfor %}</td></tr>
|
||||
<tr><td>WG technical advisors:</td><td>{% for n in info.techadv %}{{ n }}{% if not forloop.last %}, {% endif %}{% endfor %}</td></tr>
|
||||
{% endif %}
|
||||
<tr><td>Assigned AD:</td><td>{% if not snapshot %}{{ wg.ad }}{% else %}{{ gh.ad }}{% endif %}</td></tr>
|
||||
|
||||
{% if not snapshot %}
|
||||
<tr><td colspan='2'><hr size='1' noshade /></td></tr>
|
||||
|
||||
<tr><td>Mailing list:</td><td><a href="mailto:{{ wg.list_email }}">{{ wg.list_email }}</a>{% if info.prev_list_email %}<br />(previous lists: {% for a in info.prev_list_email %}{{ a }}{% if not forloop.last %}, {% else %}){% endif %}{% endfor %}{% endif %}</td></tr>
|
||||
<tr><td>Mailing list subscribe:</td><td><a href="{{ wg.list_subscribe }}">{{ wg.list_subscribe }}</a>{% if info.prev_list_subscribe %}<br />(previous archives: {% for a in info.prev_list_subscribe %}<a href="{{ a }}">{{ a }}</a>{% if not forloop.last %}, {% endif %}{% endfor %}){% endif %}</td></tr>
|
||||
<tr><td>Mailing list archive:</td><td><a href="{{ wg.list_archive }}">{{ wg.list_archive }}</a>{% if info.prev_list_archive %}<br />(previous archives: {% for a in info.prev_list_archive %}<a href="{{ a }}">{{ a }}</a>{% if not forloop.last %}, {% endif %}{% endfor %}){% endif %}</td></tr>
|
||||
<tr><td>Other web sites:</td><td>{% for a in wg.groupurl_set.all %}<a href="{{ a.url }}">{{ a.url }}</a> {% if a.name %}({{ a.name }}){% endif %}{% if not forloop.last %}<br />{% endif %}{% endfor %}</td></tr>
|
||||
|
||||
<tr><td colspan='2'><hr size='1' noshade /></td></tr>
|
||||
|
||||
<tr><td>WG State:</td><td> {{ wg.state|safe }} </td>
|
||||
{% ifnotequal wg.state_id "conclude" %}<tr><td><a href="/wgrecord/help/state/">Charter State</>:</td><td> {{ wg.charter.charter_state|safe }} {% ifequal wg.state_id "proposed" %}{% ifnotequal wg.charter.charter_state_id "notrev" %}(Initial Chartering){% endifnotequal %}{% else %}{% ifnotequal wg.charter.charter_state_id "approved" %}(Rechartering){% endifnotequal %}{% endifequal %}</td>{% endifnotequal %}
|
||||
{% ifequal wg.state_id "proposed" %}
|
||||
{% if wg.comments %}
|
||||
<tr><td>Reason for chartering:</td><td>{{ wg.comments }}</td></tr>
|
||||
{% endif %}
|
||||
{% endifequal %}
|
||||
{% ifequal wg.state_id "active" %}
|
||||
{% ifnotequal wg.charter.charter_state_id "approved" %}
|
||||
{% if wg.comments %}
|
||||
<tr><td>Reason for rechartering:</td><td>{{ wg.comments }}</td></tr>
|
||||
{% endif %}
|
||||
{% endifnotequal %}
|
||||
{% endifequal %}
|
||||
|
||||
<tr><td colspan='2'><hr size='1' noshade /></td></tr>
|
||||
|
||||
<tr><td>Last updated:</td><td> {{ info.last_update|date:"Y-m-d"|default:"(data missing)" }}</td></tr>
|
||||
<tr><td colspan='2'><hr size='1' noshade /></td></tr>
|
||||
|
||||
{% endif %}{# if not snapshot #}
|
||||
|
||||
{% endblock record_metatable %}
|
||||
|
||||
{% block record_metalinks %}
|
||||
{% if not snapshot %}
|
||||
<a href="/feed/wgcomments/{{ wg.acronym }}/">Atom feed</a>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block charter_text %}
|
||||
{% ifnotequal charter.rev "" %}
|
||||
<p>Other versions: <a href="{{ charter_text_url }}{{charter.name}}-{{rev}}.txt">plain text</a></p>
|
||||
|
||||
<h3>Charter {{ charter.name }}-{{ rev }}</h3>
|
||||
|
||||
<div class="markup_draft">
|
||||
{{ content|fill:"80"|safe|linebreaksbr|keep_spacing|sanitize_html|safe }}
|
||||
</div>
|
||||
|
||||
{% else %}
|
||||
<h3>The WG does not yet have a charter</h3>
|
||||
{% endifnotequal %}
|
||||
{% endblock %}{# charter_text #}
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
{% extends "wgrecord/record_main.html" %}
|
||||
{% comment %}
|
||||
Copyright The IETF Trust 2011, All Rights Reserved
|
||||
{% endcomment %}
|
||||
|
||||
{% load ietf_filters %}
|
||||
|
||||
{% block tab_content %}
|
||||
{% include "wgrecord/charter_diffs.html" %}
|
||||
<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="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 %}
|
||||
|
||||
{% include "wgrecord/record_history.html" %}
|
||||
{% endblock tab_content %}
|
|
@ -1,37 +0,0 @@
|
|||
{% extends "wgrecord/record_main.html" %}
|
||||
{% comment %}
|
||||
Copyright The IETF Trust 2011, All Rights Reserved
|
||||
{% endcomment %}
|
||||
|
||||
{% load ietf_filters %}
|
||||
|
||||
{% block tab_content %}
|
||||
<h3>WG Review Announcement</h3>
|
||||
{% if user|in_group:"Area_Director,Secretariat" %}
|
||||
<div style="background:#E0E0FF">
|
||||
<p align=right>
|
||||
<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 %}
|
||||
<pre>
|
||||
{{ info.review_text|escape|urlize }}
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<h3>WG Action Announcement</h3>
|
||||
{% if user|in_group:"Area_Director,Secretariat" %}
|
||||
<div style="background:#E0E0FF">
|
||||
<p align=right>
|
||||
<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 %}
|
||||
<pre>
|
||||
{{ info.action_text|escape|urlize }}
|
||||
</pre>
|
||||
|
||||
</div>
|
||||
{% endblock tab_content %}
|
|
@ -1,139 +0,0 @@
|
|||
{% comment %}
|
||||
Copyright The IETF Trust 2011, All Rights Reserved
|
||||
{% endcomment %}
|
||||
|
||||
<form name="search_form" id="search_form" class="search_form" action="/wgrecord/search/" method="get">
|
||||
|
||||
<div class="search_field">
|
||||
<label>Name/acronym:</label> {{ form.nameacronym }}
|
||||
</div>
|
||||
<div class="search_field">
|
||||
<label>Types:</label>
|
||||
<table id="search_types">
|
||||
<tr><td>{{ form.inprocess }} WGs (in chartering process)</td></tr>
|
||||
<tr><td>{{ form.active }} WGs (approved charter)</td></tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<span onclick="toggleAdvanced();"><b><img src="/images/{% if meta.advanced %}minus{% else %}plus{% endif %}.png" alt="" id="search_advanced-img" /> Advanced</b></span>
|
||||
|
||||
<div id="search_advanced" style="{% if not meta.advanced %}display:none;{%endif%}margin-top:1em;">
|
||||
Additional search criteria:
|
||||
|
||||
<div class="search_field">
|
||||
<label><input type="radio" class="radio" name="by" value="state" {% ifequal meta.by "state" %}checked="checked"{% endifequal %} onclick="changeBy();"/> State:</label> {{ form.state }} :: {{ form.charter_state }}
|
||||
</div>
|
||||
<div class="search_field">
|
||||
<label><input type="radio" class="radio" name="by" value="ad" {% ifequal meta.by "ad" %}checked="checked"{% endifequal %} onclick="changeBy();"/> Assigned AD:</label> {{ form.ad }}
|
||||
</div>
|
||||
<div class="search_field">
|
||||
<label><input type="radio" class="radio" name="by" value="area" {% ifequal meta.by "area" %}checked="checked"{% endifequal %} onclick="changeBy();"/> Area:</label> {{ form.area }}
|
||||
</div>
|
||||
<div class="search_field">
|
||||
<label><input type="radio" class="radio" name="by" value="anyfield" {% ifequal meta.by "anyfield" %}checked="checked"{% endifequal %} onclick="changeBy();"/> Text in any field:</label> {{ form.anyfield }}
|
||||
</div>
|
||||
<div class="search_field">
|
||||
<label><input type="radio" class="radio" name="by" value="eacronym" {% ifequal meta.by "eacronym" %}checked="checked"{% endifequal %} onclick="changeBy();"/> Earlier acronym:</label> {{ form.eacronym }}
|
||||
</div>
|
||||
</div><!-- end of advanced -->
|
||||
|
||||
<div style="padding-top:0.5em;">
|
||||
<span class="first-child">
|
||||
<button type="submit" name="search_submit" id="id_search_submit">Search</button>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
<script type="text/javascript">
|
||||
//<![CDATA[
|
||||
// we want to disable our submit button if we have no search text,
|
||||
// and we have no advanced options selected
|
||||
function toggleSubmit() {
|
||||
var button = document.getElementById("id_search_submit");
|
||||
var by = findCheckedSearchBy();
|
||||
var value = findSearchByValue(by);
|
||||
var active = document.getElementById("id_active");
|
||||
var text = document.getElementById("id_nameacronym");
|
||||
if ((value == "") && (text.value == "" && active.checked)) {
|
||||
button.disabled = true;
|
||||
} else {
|
||||
button.disabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
// check our button status after every change to text fields
|
||||
// Internet Explorer uses 'onpropertychange', everyone else 'oninput'
|
||||
window.oninput = toggleSubmit;
|
||||
window.onpropertychange = toggleSubmit;
|
||||
|
||||
// check our button status after every change to selection pulldowns
|
||||
window.onchange = toggleSubmit;
|
||||
|
||||
function togglePlusMinus(id) {
|
||||
var el = document.getElementById(id);
|
||||
var imgEl = document.getElementById(id+"-img");
|
||||
if (el.style.display == 'none') {
|
||||
el.style.display = 'block';
|
||||
imgEl.src = "/images/minus.png";
|
||||
} else {
|
||||
el.style.display = 'none';
|
||||
imgEl.src = "/images/plus.png";
|
||||
}
|
||||
}
|
||||
|
||||
function findCheckedSearchBy() {
|
||||
var by='';
|
||||
var f = document.search_form;
|
||||
for (var i = 0; i < f.by.length; i++) {
|
||||
if (f.by[i].checked) {
|
||||
by = f.by[i].value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return by;
|
||||
}
|
||||
|
||||
function findSearchByValue(by) {
|
||||
if (by == 'state') {
|
||||
// state might be wg state...
|
||||
state_value = document.getElementById("id_state").value;
|
||||
if (state_value) { return state_value; }
|
||||
// ...or charter state
|
||||
return document.getElementById("id_charter_state").value;
|
||||
}
|
||||
if (by == 'ad') { return document.getElementById("id_ad").value; }
|
||||
if (by == 'area') { return document.getElementById("id_area").value; }
|
||||
if (by == 'anyfield') { return document.getElementById("id_anyfield").value; }
|
||||
if (by == 'eacronym') { return document.getElementById("id_eacronym").value; }
|
||||
return '';
|
||||
}
|
||||
|
||||
function changeBy() {
|
||||
var by=findCheckedSearchBy();
|
||||
var f = document.search_form;
|
||||
f.state.disabled=true; f.charter_state.disabled=true;
|
||||
f.ad.disabled=true;
|
||||
f.area.disabled=true;
|
||||
f.anyfield.disabled=true;
|
||||
f.eacronym.disabled=true;
|
||||
if (by=='state') { f.state.disabled=false; f.charter_state.disabled=false;}
|
||||
if (by=='ad') { f.ad.disabled=false; }
|
||||
if (by=='area') { f.area.disabled=false;}
|
||||
if (by=='anyfield') { f.anyfield.disabled=false;}
|
||||
if (by=='eacronym') { f.eacronym.disabled=false;}
|
||||
|
||||
toggleSubmit();
|
||||
}
|
||||
|
||||
function toggleAdvanced() {
|
||||
togglePlusMinus("search_advanced");
|
||||
var f = document.search_form;
|
||||
for (var i = 0; i < f.by.length; i++) { f.by[i].checked = false; }
|
||||
changeBy();
|
||||
}
|
||||
|
||||
changeBy();
|
||||
|
||||
//]]>
|
||||
</script>
|
|
@ -1,25 +0,0 @@
|
|||
{% extends "base.html" %}
|
||||
{% comment %}
|
||||
Copyright 2011 The IETF Trust. All rights reserved.
|
||||
{% endcomment %}
|
||||
|
||||
{% block title %}Working Group Records{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h1>Working Group Records</h1>
|
||||
|
||||
<div class="ietf-box search_form_box">
|
||||
{% include "wgrecord/search_form.html" %}
|
||||
</div>
|
||||
|
||||
<div id="search_results">
|
||||
{% if meta.searching %}
|
||||
{% include "wgrecord/search_results.html" %}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock content %}
|
||||
{% block scripts %}
|
||||
YAHOO.util.Event.onContentReady("search_submit_button", function () {
|
||||
var oButton = new YAHOO.widget.Button("search_submit_button", {});
|
||||
});
|
||||
{% endblock scripts %}
|
|
@ -1,13 +0,0 @@
|
|||
{% comment %}
|
||||
Copyright The IETF Trust 2011, All Rights Reserved
|
||||
{% endcomment %}
|
||||
|
||||
{% load ietf_filters %}
|
||||
<tr class="{% cycle oddrow,evenrow %}">
|
||||
<td class="acronym">
|
||||
<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" %}
|
||||
{% include "wgrecord/status_columns.html" %}
|
||||
</tr>
|
|
@ -1,22 +0,0 @@
|
|||
{% comment %}
|
||||
Copyright The IETF Trust 2011, All Rights Reserved
|
||||
{% endcomment %}
|
||||
|
||||
{% if meta.max %}
|
||||
<p><b>Too many WGs match the query! Returning partial result only.</b></p>
|
||||
{% endif %}
|
||||
{% if not recs %}
|
||||
<p><b>No WGs match your query.</b></p>
|
||||
{% else %}
|
||||
<table class="ietf-table ietf-doctable">
|
||||
<tr>
|
||||
{% for hdr in meta.hdrs %}
|
||||
{% include "wgrecord/table_header.html" %}
|
||||
{% endfor %}
|
||||
</tr>
|
||||
{% for wg in recs %}
|
||||
{% include "wgrecord/search_result_row.html" %}
|
||||
{% endfor %}
|
||||
|
||||
</table>
|
||||
{% endif %}
|
|
@ -1,40 +0,0 @@
|
|||
{% extends "base.html" %}
|
||||
{% load ietf_filters %}
|
||||
{% block title %}Send ballot position email for {{ ad }}{% endblock %}
|
||||
|
||||
{% block morecss %}
|
||||
form.send-ballot pre {
|
||||
margin: 0;
|
||||
padding: 4px;
|
||||
border-top: 4px solid #eee;
|
||||
border-bottom: 4px solid #eee;
|
||||
}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h1>Send ballot position email for {{ ad }}</h1>
|
||||
|
||||
<form class="send-ballot" action="" method="POST">
|
||||
<table>
|
||||
<tr><th>From:</th> <td>{{ frm }}</td></tr>
|
||||
<tr><th>To:</th> <td>{{ to }}</td></tr>
|
||||
<tr>
|
||||
<th>Cc:<br/>
|
||||
<span class="help">separated<br/> by comma</span></th>
|
||||
<td><input type="text" name="cc" value="" size="75" /></td>
|
||||
</tr>
|
||||
<tr><th>Subject:</th> <td>{{ subject }}</td></tr>
|
||||
<tr>
|
||||
<th>Body:</th>
|
||||
<td><pre>{{ body|wrap_text }}</pre></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="actions">
|
||||
<a href="{{ back_url }}">Back</a>
|
||||
<input type="submit" value="Send"/>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
{% endblock %}
|
|
@ -1,32 +0,0 @@
|
|||
{% extends "base.html" %}
|
||||
{# Copyright The IETF Trust 2011, All Rights Reserved #}
|
||||
|
||||
{% block title %}Charter States{% endblock %}
|
||||
|
||||
{% block morecss %}
|
||||
.state_column {
|
||||
width: 13em;
|
||||
}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<h1>Charter States</h1>
|
||||
|
||||
<table class="ietf-table">
|
||||
|
||||
<tr>
|
||||
<th class="state_column">State</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
|
||||
<tr class="{% cycle oddrow,evenrow as cycle1 %}"></tr>
|
||||
{% for state in states %}
|
||||
<tr class="{% cycle cycle1 %}">
|
||||
<td>{{ state.name|escape }}</td>
|
||||
<td>{{ state.desc|escape }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
|
||||
{% endblock %}
|
|
@ -1,17 +0,0 @@
|
|||
{% comment %}
|
||||
Copyright The IETF Trust 2011, All Rights Reserved
|
||||
{% endcomment %}
|
||||
{% load ietf_filters ietf_streams %}{% load wg_ballot_icon %}
|
||||
<td class="status">
|
||||
{% if wg.charter %}
|
||||
{{ wg.charter.charter_state|safe }} {% ifequal wg.state_id "proposed" %}{% ifnotequal wg.charter.charter_state_id "notrev" %}(Initial Chartering){% endifnotequal %}{% else %}{% ifnotequal wg.charter.charter_state_id "approved" %}(Rechartering){% endifnotequal %}{% endifequal %}
|
||||
{% else %}
|
||||
(data missing)
|
||||
{% endif %}
|
||||
{% if wg.charter.telechat_date %}<br/>IESG Telechat: {{ wg.charter.telechat_date }}{% endif %}
|
||||
|
||||
{% block extra_status %}{% endblock %}
|
||||
</td>
|
||||
<td class="ballot">
|
||||
{% ifequal wg.charter.charter_state_id "iesgrev" %}{% wg_ballot_icon wg.acronym %}{% endifequal %}
|
||||
</td>
|
|
@ -1,40 +0,0 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block morecss %}
|
||||
form #id_content {
|
||||
width: 40em;
|
||||
height: 600px;
|
||||
}
|
||||
{% endblock %}
|
||||
|
||||
{% block title %}
|
||||
Charter submission for {{ wg.acronym }}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h1>Charter submission for {{ wg.acronym }}</h1>
|
||||
|
||||
<p>The text will be submitted as <strong>charter-ietf-{{ wg.acronym }}-{{ next_rev }}</strong></p>
|
||||
<form class="edit-info" action="" enctype="multipart/form-data" method="POST">
|
||||
<table>
|
||||
{% for field in form.visible_fields %}
|
||||
<tr>
|
||||
<th>{{ field.label_tag }}:</th>
|
||||
<td>
|
||||
{{ field }}
|
||||
{% if field.help_text %}<div class="help">{{ field.help_text }}</div>{% endif %}
|
||||
{{ field.errors }}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="actions">
|
||||
<a href="{% url wg_view_record name=wg.acronym %}">Back</a>
|
||||
<input type="submit" value="Submit"/>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
|
||||
{% endblock %}
|
|
@ -1,15 +0,0 @@
|
|||
{# Copyright The IETF Trust 2011, All Rights Reserved #}
|
||||
|
||||
<th class="{{hdr.htype}}"{% if hdr.colspan %}colspan="{{ hdr.colspan }}" {% endif %}
|
||||
onclick="location=unescape('{{ meta.rqps }}&sortBy={{hdr.htype}}');"
|
||||
style="white-space: nowrap;"
|
||||
>
|
||||
<span>
|
||||
<label>{{hdr.htitle}}</label>
|
||||
{% if hdr.selected %}
|
||||
<img style="border-style: none;vertical-align:top" src="/images/sort-header-filled.png"/>
|
||||
{% else %}
|
||||
<img style="border-style: none;vertical-align:top" src="/images/sort-header-clear.png"/>
|
||||
{% endif %}
|
||||
</span>
|
||||
</th>
|
|
@ -1 +0,0 @@
|
|||
IETF Working Group {{ wg.name }} ({{ wg.acronym }}){% if wg.parent %} under the {{ wg.parent }}{% endif %}
|
|
@ -1 +0,0 @@
|
|||
{{ wg.name }} ({{wg.acronym}})
|
|
@ -1 +0,0 @@
|
|||
#
|
|
@ -1,67 +0,0 @@
|
|||
# Copyright The IETF Trust 2011, All Rights Reserved
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib.syndication.feeds import Feed, FeedDoesNotExist
|
||||
from django.utils.feedgenerator import Atom1Feed
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
from django.core.urlresolvers import reverse
|
||||
from ietf.utils.history import find_history_active_at
|
||||
|
||||
from redesign.group.models import Group
|
||||
from ietf.wgrecord.views_rec import _get_history, _get_html
|
||||
from wgrecord import markup_txt
|
||||
import datetime
|
||||
import re, os
|
||||
|
||||
class GroupComments(Feed):
|
||||
feed_type = Atom1Feed
|
||||
title_template = "feeds/wg_record_title.html"
|
||||
description_template = "feeds/wg_record_description.html"
|
||||
def get_object(self, bits):
|
||||
if len(bits) != 1:
|
||||
raise ObjectDoesNotExist
|
||||
return Group.objects.get(acronym=bits[0])
|
||||
|
||||
def title(self, obj):
|
||||
return "WG Record changes for %s" % obj.acronym
|
||||
|
||||
def link(self, obj):
|
||||
if obj is None:
|
||||
raise FeedDoesNotExist
|
||||
return reverse('wg_view_record', kwargs={'name': obj.acronym})
|
||||
|
||||
def description(self, obj):
|
||||
return self.title(obj)
|
||||
|
||||
def items(self, obj):
|
||||
history = _get_history(obj)
|
||||
for h in history:
|
||||
gh = find_history_active_at(obj, h['date'])
|
||||
if gh:
|
||||
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'] = [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
|
||||
h['charter'] = _get_html(
|
||||
str(dh.name)+"-"+str(dh.rev)+",html",
|
||||
os.path.join(dh.get_file_path(), dh.name+"-"+dh.rev+".txt"))
|
||||
else:
|
||||
h['rev'] = obj.charter.rev
|
||||
h['charter'] = _get_html(
|
||||
"charter-ietf-"+str(obj.acronym)+"-"+str(obj.charter.rev)+",html",
|
||||
os.path.join(obj.charter.get_file_path(), "charter-ietf-"+obj.acronym+"-"+obj.charter.rev+".txt"))
|
||||
return history
|
||||
|
||||
def item_link(self, obj):
|
||||
return reverse('wg_view_record', kwargs={'name': obj['group'].acronym})
|
||||
|
||||
def item_pubdate(self, obj):
|
||||
return obj['date']
|
||||
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
# generation of mails
|
||||
|
||||
import textwrap
|
||||
from datetime import datetime, date, time, timedelta
|
||||
|
||||
from django.template.loader import render_to_string
|
||||
from django.utils.html import strip_tags
|
||||
from django.conf import settings
|
||||
from django.core.urlresolvers import reverse as urlreverse
|
||||
|
||||
from ietf.utils.mail import send_mail, send_mail_text
|
||||
from ietf.idtracker.models import *
|
||||
from ietf.ipr.search import iprs_from_docs
|
||||
from redesign.doc.models import WriteupDocEvent, BallotPositionDocEvent, LastCallDocEvent, DocAlias
|
||||
from redesign.person.models import Person
|
||||
|
||||
# These become part of the subject of the email
|
||||
types = {}
|
||||
types['state'] = "State changed"
|
||||
types['state-notrev'] = "State changed to Not currently under review"
|
||||
types['state-infrev'] = "State changed to Informal review"
|
||||
types['state-intrev'] = "State changed to Internal review"
|
||||
types['state-extrev'] = "State changed to External review"
|
||||
types['state-iesgrev'] = "State changed to IESG review"
|
||||
types['state-approved'] = "Charter approved"
|
||||
types['conclude'] = "Request closing of WG"
|
||||
|
||||
def email_secretariat(request, wg, type, text):
|
||||
to = ["iesg-secretary@ietf.org"]
|
||||
|
||||
text = strip_tags(text)
|
||||
send_mail(request, to, None,
|
||||
"Regarding WG %s: %s" % (wg.acronym, types[type]),
|
||||
"wgrecord/email_secretariat.txt",
|
||||
dict(text=text,
|
||||
url=settings.IDTRACKER_BASE_URL + urlreverse('wg_view_record', kwargs=dict(name=wg.acronym))))
|
||||
|
|
@ -1,66 +0,0 @@
|
|||
# Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
|
||||
# All rights reserved. Contact: Pasi Eronen <pasi.eronen@nokia.com>
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
#
|
||||
# * Redistributions in binary form must reproduce the above
|
||||
# copyright notice, this list of conditions and the following
|
||||
# disclaimer in the documentation and/or other materials provided
|
||||
# with the distribution.
|
||||
#
|
||||
# * Neither the name of the Nokia Corporation and/or its
|
||||
# subsidiary(-ies) nor the names of its contributors may be used
|
||||
# to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
from django.utils.html import escape
|
||||
import string
|
||||
import re
|
||||
|
||||
def markup(content):
|
||||
# normalize line endings to LF only
|
||||
content = content.replace("\r\n", "\n")
|
||||
content = content.replace("\r", "\n")
|
||||
|
||||
# at this point, "content" is normal string
|
||||
# fix most common non-ASCII characters
|
||||
t1 = string.maketrans("\x91\x92\x93\x94\x95\x96\x97\xc6\xe8\xe9", "\'\'\"\"o--\'ee")
|
||||
# map everything except printable ASCII, TAB, LF, FF to "?"
|
||||
t2 = string.maketrans('','')
|
||||
t3 = "?"*9 + "\t\n?\f" + "?"*19 + t2[32:127] + "?"*129
|
||||
t4 = t1.translate(t3)
|
||||
content = content.translate(t4)
|
||||
|
||||
# remove leading white space
|
||||
content = content.lstrip()
|
||||
# remove runs of blank lines
|
||||
content = re.sub("\n\n\n+", "\n\n", content)
|
||||
|
||||
# expand tabs + escape
|
||||
content = escape(content.expandtabs())
|
||||
|
||||
content = re.sub("\n(.+\[Page \d+\])\n\f\n(.+)\n", """\n<span class="m_ftr">\g<1></span>\n<span class="m_hdr">\g<2></span>\n""", content)
|
||||
content = re.sub("\n(.+\[Page \d+\])\n\s*$", """\n<span class="m_ftr">\g<1></span>\n""", content)
|
||||
# remove remaining FFs (to be valid XHTML)
|
||||
content = content.replace("\f","\n")
|
||||
|
||||
content = re.sub("\n\n([0-9]+\\.|[A-Z]\\.[0-9]|Appendix|Status of|Abstract|Table of|Full Copyright|Copyright|Intellectual Property|Acknowled|Author|Index)(.*)(?=\n\n)", """\n\n<span class="m_h">\g<1>\g<2></span>""", content)
|
||||
|
||||
return "<pre>"+content+"</pre>\n"
|
|
@ -1 +0,0 @@
|
|||
#
|
|
@ -1,124 +0,0 @@
|
|||
# Copyright The IETF Trust 2011, All Rights Reserved
|
||||
|
||||
from django import template
|
||||
from django.core.urlresolvers import reverse as urlreverse
|
||||
from django.conf import settings
|
||||
from ietf.idtracker.templatetags.ietf_filters import in_group, timesince_days
|
||||
from redesign.doc.models import GroupBallotPositionDocEvent
|
||||
from redesign.person.models import Person
|
||||
from redesign.group.models import Group
|
||||
|
||||
register = template.Library()
|
||||
|
||||
def get_user_adid(context):
|
||||
if 'user' in context and in_group(context['user'], "Area_Director"):
|
||||
return context['user'].get_profile().id
|
||||
else:
|
||||
return None
|
||||
|
||||
def get_user_name(context):
|
||||
if 'user' in context and context['user'].is_authenticated():
|
||||
from person.models import Person
|
||||
try:
|
||||
return context['user'].get_profile().name
|
||||
except Person.DoesNotExist:
|
||||
return None
|
||||
|
||||
def render_ballot_icon(context, name):
|
||||
wg = Group.objects.get(acronym=name)
|
||||
doc = wg.charter
|
||||
adId = get_user_adid(context)
|
||||
red = 0
|
||||
green = 0
|
||||
yellow = 0
|
||||
gray = 0
|
||||
blank = 0
|
||||
my = None
|
||||
|
||||
active_ads = list(Person.objects.filter(email__role__name="ad",
|
||||
email__role__group__type="area",
|
||||
email__role__group__state="active").distinct())
|
||||
started_process = doc.latest_event(type="started_iesg_process")
|
||||
latest_positions = []
|
||||
for p in active_ads:
|
||||
p_pos = list(GroupBallotPositionDocEvent.objects.filter(doc=doc, ad=p).order_by("-time"))
|
||||
if p_pos != []:
|
||||
latest_positions.append(p_pos[0])
|
||||
for p in latest_positions:
|
||||
if not p.pos_id:
|
||||
blank = blank + 1
|
||||
elif (p.pos_id == "yes"):
|
||||
green = green + 1
|
||||
elif (p.pos_id == "no"):
|
||||
green = green + 1
|
||||
elif (p.pos_id == "block"):
|
||||
red = red + 1
|
||||
elif (p.pos_id == "abstain"):
|
||||
yellow = yellow + 1
|
||||
else:
|
||||
blank = blank + 1
|
||||
if adId and (p.ad_id == adId):
|
||||
my = p.pos.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('wg_edit_position', kwargs=dict(name=acronym))
|
||||
if adId:
|
||||
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="showWGBallot(\'' + acronym + '\',\'' + str(edit_position_url) + '\')"'+res_cm+'>'
|
||||
for y in range(3):
|
||||
res = res + "<tr>"
|
||||
for x in range(5):
|
||||
myMark = False
|
||||
if red > 0:
|
||||
c = "ballot_icon_red"
|
||||
red = red - 1
|
||||
myMark = (my == "Block")
|
||||
elif yellow > 0:
|
||||
c = "ballot_icon_yellow"
|
||||
yellow = yellow - 1
|
||||
myMark = (my == "Abstain")
|
||||
elif green > 0:
|
||||
c = "ballot_icon_green"
|
||||
green = green - 1
|
||||
myMark = (my == "Yes") or (my == "No")
|
||||
else:
|
||||
c = ""
|
||||
myMark = (y == 2) and (x == 4) and (my == "No Record")
|
||||
if myMark:
|
||||
res = res + '<td class="'+c+' ballot_icon_my" />'
|
||||
my = None
|
||||
else:
|
||||
res = res + '<td class="'+c+'" />'
|
||||
res = res + '</tr>'
|
||||
res = res + '</table>'
|
||||
return res
|
||||
|
||||
|
||||
class BallotIconNode(template.Node):
|
||||
def __init__(self, doc_var):
|
||||
self.doc_var = doc_var
|
||||
def render(self, context):
|
||||
doc = template.resolve_variable(self.doc_var, context)
|
||||
return render_ballot_icon(context, doc)
|
||||
|
||||
def do_ballot_icon(parser, token):
|
||||
try:
|
||||
tagName, docName = token.split_contents()
|
||||
except ValueError:
|
||||
raise template.TemplateSyntaxError, "%r tag requires exactly two arguments" % token.contents.split()[0]
|
||||
return BallotIconNode(docName)
|
||||
|
||||
register.tag('wg_ballot_icon', do_ballot_icon)
|
||||
|
||||
@register.filter
|
||||
def my_position(doc, user):
|
||||
user_name = get_user_name({'user':user})
|
||||
p_pos = list(GroupBallotPositionDocEvent.objects.filter(doc=doc, ad=Person.objects.get(user__name=user_name)).order_by("-time"))
|
||||
if p_pos == []:
|
||||
return "No record"
|
||||
else:
|
||||
return p_pos[0].pos.name
|
||||
|
|
@ -1,654 +0,0 @@
|
|||
# Copyright The IETF Trust 2011, All Rights Reserved
|
||||
|
||||
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
|
||||
|
||||
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__)
|
||||
|
||||
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-core-01.txt")
|
||||
if not os.path.exists(fpath):
|
||||
print "\nERROR: charter text not found in "+settings.CHARTER_PATH
|
||||
print "Needed for testing WG record pages."
|
||||
print "Remember to set CHARTER_PATH in settings.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)
|
||||
|
||||
class WgAddCommentTestCase(django.test.TestCase):
|
||||
fixtures = ['names']
|
||||
|
||||
def test_add_comment(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")
|
||||
|
||||
group = Group.objects.get(acronym="mars")
|
||||
url = urlreverse('wg_add_comment', 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=comment]')), 1)
|
||||
|
||||
# request resurrect
|
||||
comments_before = group.groupevent_set.filter(type="added_comment").count()
|
||||
|
||||
r = self.client.post(url, dict(comment="This is a test."))
|
||||
self.assertEquals(r.status_code, 302)
|
||||
|
||||
self.assertEquals(group.groupevent_set.filter(type="added_comment").count(), comments_before + 1)
|
||||
self.assertTrue("This is a test." in group.groupevent_set.filter(type="added_comment").order_by('-time')[0].desc)
|
||||
|
||||
class WgEditPositionTestCase(django.test.TestCase):
|
||||
fixtures = ['names', 'ballot']
|
||||
|
||||
def test_edit_position(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")
|
||||
no = name(GroupBallotPositionName, 'no', 'No'),
|
||||
yes = name(GroupBallotPositionName, 'yes', 'Yes'),
|
||||
abstain = name(GroupBallotPositionName, 'abstain', 'Abstain'),
|
||||
block = name(GroupBallotPositionName, 'block', 'Block'),
|
||||
norecord = name(GroupBallotPositionName, 'norecord', 'No record'),
|
||||
|
||||
group = Group.objects.get(acronym="mars")
|
||||
url = urlreverse('wg_edit_position', kwargs=dict(name=group.acronym))
|
||||
login_testing_unauthorized(self, "ad", url)
|
||||
|
||||
charter = set_or_create_charter(group)
|
||||
|
||||
p = Person.objects.get(name="Aread Irector")
|
||||
|
||||
e = DocEvent()
|
||||
e.type = "started_iesg_process"
|
||||
e.by = p
|
||||
e.doc = charter
|
||||
e.desc = "IESG process started"
|
||||
e.save()
|
||||
|
||||
charter.charter_state = iesgrev
|
||||
charter.save()
|
||||
|
||||
# normal get
|
||||
r = self.client.get(url)
|
||||
self.assertEquals(r.status_code, 200)
|
||||
q = PyQuery(r.content)
|
||||
self.assertTrue(len(q('form input[name=position]')) > 0)
|
||||
self.assertEquals(len(q('form textarea[name=comment]')), 1)
|
||||
|
||||
# vote
|
||||
pos_before = charter.docevent_set.filter(type="changed_ballot_position").count()
|
||||
self.assertTrue(not charter.docevent_set.filter(type="changed_ballot_position", by__name="Aread Irector"))
|
||||
|
||||
r = self.client.post(url, dict(position="block",
|
||||
block_comment="This is a blocking test.",
|
||||
comment="This is a test."))
|
||||
self.assertEquals(r.status_code, 302)
|
||||
|
||||
self.assertEquals(charter.docevent_set.filter(type="changed_ballot_position").count(), pos_before + 1)
|
||||
e = charter.latest_event(GroupBallotPositionDocEvent)
|
||||
self.assertTrue("This is a blocking test." in e.block_comment)
|
||||
self.assertTrue("This is a test." in e.comment)
|
||||
self.assertTrue(e.pos_id, "block")
|
||||
|
||||
# recast vote
|
||||
pos_before = charter.docevent_set.filter(type="changed_ballot_position").count()
|
||||
|
||||
r = self.client.post(url, dict(position="yes"))
|
||||
self.assertEquals(r.status_code, 302)
|
||||
|
||||
self.assertEquals(charter.docevent_set.filter(type="changed_ballot_position").count(), pos_before + 1)
|
||||
e = charter.latest_event(GroupBallotPositionDocEvent)
|
||||
self.assertTrue(e.pos_id, "yes")
|
||||
|
||||
# clear vote
|
||||
pos_before = charter.docevent_set.filter(type="changed_ballot_position").count()
|
||||
|
||||
r = self.client.post(url, dict(position="norecord"))
|
||||
self.assertEquals(r.status_code, 302)
|
||||
|
||||
self.assertEquals(charter.docevent_set.filter(type="changed_ballot_position").count(), pos_before + 1)
|
||||
e = charter.latest_event(GroupBallotPositionDocEvent)
|
||||
self.assertTrue(e.pos_id, "norecord")
|
||||
|
||||
def test_edit_position_as_secretary(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")
|
||||
no = name(GroupBallotPositionName, 'no', 'No'),
|
||||
yes = name(GroupBallotPositionName, 'yes', 'Yes'),
|
||||
abstain = name(GroupBallotPositionName, 'abstain', 'Abstain'),
|
||||
block = name(GroupBallotPositionName, 'block', 'Block'),
|
||||
norecord = name(GroupBallotPositionName, 'norecord', 'No record'),
|
||||
|
||||
group = Group.objects.get(acronym="mars")
|
||||
url = urlreverse('wg_edit_position', kwargs=dict(name=group.acronym))
|
||||
p = Person.objects.get(name="Aread Irector")
|
||||
url += "?ad=%d" % p.id
|
||||
login_testing_unauthorized(self, "secretary", url)
|
||||
|
||||
charter = set_or_create_charter(group)
|
||||
|
||||
e = DocEvent()
|
||||
e.type = "started_iesg_process"
|
||||
e.by = p
|
||||
e.doc = charter
|
||||
e.desc = "IESG process started"
|
||||
e.save()
|
||||
|
||||
charter.charter_state = iesgrev
|
||||
charter.save()
|
||||
|
||||
# normal get
|
||||
r = self.client.get(url)
|
||||
self.assertEquals(r.status_code, 200)
|
||||
q = PyQuery(r.content)
|
||||
self.assertTrue(len(q('form input[name=position]')) > 0)
|
||||
|
||||
# vote for rhousley
|
||||
pos_before = charter.docevent_set.filter(type="changed_ballot_position").count()
|
||||
self.assertTrue(not charter.docevent_set.filter(type="changed_ballot_position", by__name="Sec Retary"))
|
||||
|
||||
r = self.client.post(url, dict(position="no"))
|
||||
self.assertEquals(r.status_code, 302)
|
||||
|
||||
self.assertEquals(charter.docevent_set.filter(type="changed_ballot_position").count(), pos_before + 1)
|
||||
e = charter.latest_event(GroupBallotPositionDocEvent)
|
||||
self.assertTrue(e.pos_id, "no")
|
||||
|
||||
def test_send_ballot_comment(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")
|
||||
no = name(GroupBallotPositionName, 'no', 'No'),
|
||||
yes = name(GroupBallotPositionName, 'yes', 'Yes'),
|
||||
abstain = name(GroupBallotPositionName, 'abstain', 'Abstain'),
|
||||
block = name(GroupBallotPositionName, 'block', 'Block'),
|
||||
norecord = name(GroupBallotPositionName, 'norecord', 'No record'),
|
||||
|
||||
group = Group.objects.get(acronym="mars")
|
||||
url = urlreverse('wg_send_ballot_comment', kwargs=dict(name=group.acronym))
|
||||
login_testing_unauthorized(self, "ad", url)
|
||||
|
||||
charter = set_or_create_charter(group)
|
||||
|
||||
p = Person.objects.get(name="Aread Irector")
|
||||
|
||||
e = DocEvent()
|
||||
e.type = "started_iesg_process"
|
||||
e.by = p
|
||||
e.doc = charter
|
||||
e.desc = "IESG process started"
|
||||
e.save()
|
||||
|
||||
charter.charter_state = iesgrev
|
||||
charter.save()
|
||||
|
||||
GroupBallotPositionDocEvent.objects.create(
|
||||
doc=charter,
|
||||
by=p,
|
||||
type="changed_ballot_position",
|
||||
pos=GroupBallotPositionName.objects.get(slug="block"),
|
||||
ad=p,
|
||||
block_comment="This is a block test",
|
||||
comment="This is a test",
|
||||
)
|
||||
|
||||
# normal get
|
||||
r = self.client.get(url)
|
||||
self.assertEquals(r.status_code, 200)
|
||||
q = PyQuery(r.content)
|
||||
self.assertTrue(len(q('form input[name="cc"]')) > 0)
|
||||
|
||||
# send
|
||||
p = Person.objects.get(name="Aread Irector")
|
||||
mailbox_before = len(mail_outbox)
|
||||
|
||||
r = self.client.post(url, dict(cc="test@example.com", cc_state_change="1"))
|
||||
self.assertEquals(r.status_code, 302)
|
||||
|
||||
self.assertEquals(len(mail_outbox), mailbox_before + 1)
|
||||
self.assertTrue("BLOCKING COMMENT" in mail_outbox[-1]['Subject'])
|
||||
self.assertTrue("COMMENT" in mail_outbox[-1]['Subject'])
|
||||
|
||||
class WgApproveBallotTestCase(django.test.TestCase):
|
||||
fixtures = ['base', 'names', 'ballot']
|
||||
|
||||
def test_approve_ballot(self):
|
||||
make_test_data()
|
||||
# Make sure all relevant names are created
|
||||
type_charter = name(DocTypeName, "charter", "Charter")
|
||||
proposed = name(GroupStateName, "proposed", "Proposed")
|
||||
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")
|
||||
no = name(GroupBallotPositionName, 'no', 'No'),
|
||||
yes = name(GroupBallotPositionName, 'yes', 'Yes'),
|
||||
abstain = name(GroupBallotPositionName, 'abstain', 'Abstain'),
|
||||
block = name(GroupBallotPositionName, 'block', 'Block'),
|
||||
norecord = name(GroupBallotPositionName, 'norecord', 'No record'),
|
||||
|
||||
group = Group.objects.get(acronym="mars")
|
||||
url = urlreverse('wg_approve_ballot', kwargs=dict(name=group.acronym))
|
||||
login_testing_unauthorized(self, "secretary", url)
|
||||
|
||||
charter = set_or_create_charter(group)
|
||||
|
||||
p = Person.objects.get(name="Aread Irector")
|
||||
|
||||
e = DocEvent()
|
||||
e.type = "started_iesg_process"
|
||||
e.by = p
|
||||
e.doc = charter
|
||||
e.desc = "IESG process started"
|
||||
e.save()
|
||||
|
||||
charter.charter_state = iesgrev
|
||||
charter.save()
|
||||
|
||||
# normal get
|
||||
r = self.client.get(url)
|
||||
self.assertEquals(r.status_code, 200)
|
||||
q = PyQuery(r.content)
|
||||
self.assertTrue("Send out the announcement" in q('input[type=submit]')[0].get('value'))
|
||||
self.assertEquals(len(q('pre')), 1)
|
||||
|
||||
# approve
|
||||
mailbox_before = len(mail_outbox)
|
||||
|
||||
# Dont copy the actual txt file
|
||||
from django.conf import settings
|
||||
settings.DONT_COPY_CHARTER_ON_APPROVE = True
|
||||
|
||||
r = self.client.post(url, dict())
|
||||
self.assertEquals(r.status_code, 302)
|
||||
|
||||
charter = Document.objects.get(name=charter.name)
|
||||
self.assertEquals(charter.charter_state_id, "approved")
|
||||
|
||||
self.assertEquals(charter.rev, "01")
|
||||
|
||||
self.assertEquals(len(mail_outbox), mailbox_before + 2)
|
||||
|
||||
self.assertTrue("WG Action" in mail_outbox[-1]['Subject'])
|
||||
self.assertTrue("Charter approved" in mail_outbox[-2]['Subject'])
|
|
@ -1,55 +0,0 @@
|
|||
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/
|
||||
|
||||
#
|
||||
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
# Copyright The IETF Trust 2011, All Rights Reserved
|
||||
|
||||
from django.conf.urls.defaults import patterns, url
|
||||
from ietf.wgrecord import views_rec, views_search, views_edit, views_ballot, views_submit
|
||||
from redesign.name.models import CharterDocStateName
|
||||
|
||||
urlpatterns = patterns('django.views.generic.simple',
|
||||
url(r'^help/state/$', 'direct_to_template', { 'template': 'wgrecord/states.html', 'extra_context': { 'states': CharterDocStateName.objects.all() } }, name='help_charter_states'),
|
||||
)
|
||||
urlpatterns += patterns('',
|
||||
(r'^/?$', views_search.search_main),
|
||||
url(r'^create/$', views_edit.edit_info, name="wg_create"),
|
||||
(r'^search/$', views_search.search_results),
|
||||
(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.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/(?P<option>initcharter|recharter|abandon)/$', views_edit.change_state, name='wg_startstop_process'),
|
||||
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='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'),
|
||||
|
||||
)
|
|
@ -1,219 +0,0 @@
|
|||
from django.conf import settings
|
||||
import re
|
||||
|
||||
from datetime import datetime
|
||||
from group.models import GroupEvent
|
||||
from doc.models import Document, DocAlias, DocHistory, RelatedDocument, DocumentAuthor
|
||||
from ietf.utils.history import find_history_active_at
|
||||
|
||||
def set_or_create_charter(wg):
|
||||
try:
|
||||
charter = Document.objects.get(docalias__name="charter-ietf-%s" % wg.acronym)
|
||||
except Document.DoesNotExist:
|
||||
charter = Document.objects.create(
|
||||
name="charter-ietf-" + wg.acronym,
|
||||
time=datetime.now(),
|
||||
type_id="charter",
|
||||
title=wg.name,
|
||||
group=wg,
|
||||
abstract=wg.name,
|
||||
rev="",
|
||||
)
|
||||
# Create an alias as well
|
||||
DocAlias.objects.create(
|
||||
name = charter.name,
|
||||
document = charter
|
||||
)
|
||||
if wg.charter != charter:
|
||||
wg.charter = charter
|
||||
wg.save()
|
||||
return charter
|
||||
|
||||
def save_charter_in_history(charter):
|
||||
'''This is a modified save_document_in_history that save the name
|
||||
as charter-ietf-wgacronym with wgacronym being the current Group
|
||||
acronym. The charter Document may have an old name which is no longer
|
||||
in use'''
|
||||
def get_model_fields_as_dict(obj):
|
||||
return dict((field.name, getattr(obj, field.name))
|
||||
for field in obj._meta.fields
|
||||
if field is not obj._meta.pk)
|
||||
|
||||
# copy fields
|
||||
fields = get_model_fields_as_dict(charter)
|
||||
fields["doc"] = charter
|
||||
fields["name"] = 'charter-ietf-%s' % charter.chartered_group.acronym
|
||||
|
||||
chist = DocHistory(**fields)
|
||||
chist.save()
|
||||
|
||||
# copy many to many
|
||||
for field in charter._meta.many_to_many:
|
||||
if not field.rel.through:
|
||||
# just add the attributes
|
||||
rel = getattr(chist, field.name)
|
||||
for item in getattr(charter, field.name).all():
|
||||
rel.add(item)
|
||||
|
||||
# copy remaining tricky many to many
|
||||
def transfer_fields(obj, HistModel):
|
||||
mfields = get_model_fields_as_dict(item)
|
||||
# map charter -> chist
|
||||
for k, v in mfields.iteritems():
|
||||
if v == charter:
|
||||
mfields[k] = chist
|
||||
HistModel.objects.create(**mfields)
|
||||
|
||||
for item in RelatedDocument.objects.filter(source=charter):
|
||||
transfer_fields(item, RelatedDocHistory)
|
||||
|
||||
for item in DocumentAuthor.objects.filter(document=charter):
|
||||
transfer_fields(item, DocHistoryAuthor)
|
||||
|
||||
return chist
|
||||
|
||||
|
||||
def add_wg_comment(request, wg, text, ballot=None):
|
||||
if request:
|
||||
login = request.user.get_profile()
|
||||
else:
|
||||
login = None
|
||||
|
||||
e = GroupEvent(group=wg, type="added_comment", by=login)
|
||||
e.desc = text
|
||||
e.save()
|
||||
|
||||
def log_state_changed(request, doc, by, prev_state, note=''):
|
||||
from doc.models import DocEvent
|
||||
|
||||
e = DocEvent(doc=doc, by=by)
|
||||
e.type = "changed_document"
|
||||
e.desc = u"State changed to <b>%s</b> from %s" % (
|
||||
doc.charter_state.name,
|
||||
prev_state.name if prev_state else "None")
|
||||
|
||||
if note:
|
||||
e.desc += "<br>%s" % 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, note=''):
|
||||
from group.models import GroupEvent
|
||||
|
||||
e = GroupEvent(group=wg, by=by)
|
||||
e.type = "info_changed"
|
||||
e.desc = "WG info changed: "
|
||||
if note:
|
||||
e.desc += "<br>%s" % note
|
||||
|
||||
e.save()
|
||||
return e
|
||||
|
||||
def get_charter_for_revision(charter, r):
|
||||
if r == None:
|
||||
return None
|
||||
else:
|
||||
l = list(charter.history_set.filter(rev=r).order_by('-time'))
|
||||
if l != []:
|
||||
return l[0]
|
||||
else:
|
||||
# Get the lastest history entry
|
||||
l = list(charter.history_set.all().order_by('-time'))
|
||||
if l != []:
|
||||
class FakeHistory(object):
|
||||
def __init__(self, name, rev, time):
|
||||
self.name = name
|
||||
self.rev = rev
|
||||
self.time = time
|
||||
|
||||
return FakeHistory(l[0].name, charter.rev, charter.time)
|
||||
else:
|
||||
# no history, just return charter
|
||||
return charter
|
||||
|
||||
def get_group_for_revision(wg, r):
|
||||
if r == None:
|
||||
return None
|
||||
else:
|
||||
l = list(wg.charter.history_set.filter(rev=r).order_by('-time'))
|
||||
if l != []:
|
||||
o = list(wg.history_set.filter(time__lte=l[0].time).order_by('-time'))
|
||||
if o != []:
|
||||
return o[0]
|
||||
else:
|
||||
return wg
|
||||
else:
|
||||
return wg
|
||||
|
||||
def prev_revision(rev):
|
||||
m = re.match(r"(?P<major>[0-9][0-9])(-(?P<minor>[0-9][0-9]))?", rev)
|
||||
if m.group('minor') and m.group('minor') != "00":
|
||||
return "%s-%#02d" % (m.group('major'), int(m.group('minor')) - 1)
|
||||
else:
|
||||
return None
|
||||
|
||||
def next_revision(rev):
|
||||
if rev == "":
|
||||
return "00-00"
|
||||
m = re.match(r"(?P<major>[0-9][0-9])(-(?P<minor>[0-9][0-9]))?", rev)
|
||||
if m.group('minor'):
|
||||
return "%s-%#02d" % (m.group('major'), int(m.group('minor')) + 1)
|
||||
else:
|
||||
return "%s-00" % (m.group('major'))
|
||||
|
||||
def approved_revision(rev):
|
||||
if rev == "":
|
||||
return ""
|
||||
m = re.match(r"(?P<major>[0-9][0-9])(-(?P<minor>[0-9][0-9]))?", rev)
|
||||
return m.group('major')
|
||||
|
||||
def next_approved_revision(rev):
|
||||
if rev == "":
|
||||
return "01"
|
||||
m = re.match(r"(?P<major>[0-9][0-9])(-(?P<minor>[0-9][0-9]))?", rev)
|
||||
return "%#02d" % (int(m.group('major')) + 1)
|
||||
|
||||
def update_telechat(request, doc, by, new_telechat_date):
|
||||
from doc.models import TelechatDocEvent
|
||||
|
||||
on_agenda = bool(new_telechat_date)
|
||||
|
||||
prev = doc.latest_event(TelechatDocEvent, type="scheduled_for_telechat")
|
||||
prev_telechat = prev.telechat_date if prev else None
|
||||
prev_agenda = bool(prev_telechat)
|
||||
|
||||
e = TelechatDocEvent()
|
||||
e.type = "scheduled_for_telechat"
|
||||
e.by = by
|
||||
e.doc = doc
|
||||
e.telechat_date = new_telechat_date
|
||||
|
||||
if on_agenda != prev_agenda:
|
||||
if on_agenda:
|
||||
e.desc = "Placed on agenda for telechat - %s by %s" % (
|
||||
new_telechat_date, by.name)
|
||||
else:
|
||||
e.desc = "Removed from agenda for telechat by %s" % by.name
|
||||
e.save()
|
||||
elif on_agenda and new_telechat_date != prev_telechat:
|
||||
e.desc = "Telechat date has been changed to <b>%s</b> from <b>%s</b> by %s" % (new_telechat_date, prev_telechat, by.name)
|
||||
e.save()
|
|
@ -1,439 +0,0 @@
|
|||
# ballot management (voting, commenting, writeups, ...) for Area
|
||||
# Directors and Secretariat
|
||||
|
||||
import re, os
|
||||
from datetime import datetime, date, time, timedelta
|
||||
from django.http import HttpResponse, HttpResponseRedirect, Http404
|
||||
from django.shortcuts import render_to_response, get_object_or_404, redirect
|
||||
from django.core.urlresolvers import reverse as urlreverse
|
||||
from django.template.loader import render_to_string
|
||||
from django.template import RequestContext
|
||||
from django import forms
|
||||
from django.utils.html import strip_tags
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
|
||||
from ietf.utils.mail import send_mail_text, send_mail_preformatted
|
||||
from ietf.ietfauth.decorators import group_required
|
||||
from ietf.idtracker.templatetags.ietf_filters import in_group
|
||||
from ietf.ietfauth.decorators import has_role
|
||||
from mails import email_secretariat
|
||||
|
||||
from utils import *
|
||||
from group.models import Group, GroupHistory, GroupEvent, save_group_in_history
|
||||
from name.models import GroupBallotPositionName, CharterDocStateName, GroupStateName
|
||||
from doc.models import Document, DocEvent, GroupBallotPositionDocEvent, WriteupDocEvent
|
||||
|
||||
def default_action_text(wg, charter, user):
|
||||
e = WriteupDocEvent(doc=charter, by=user)
|
||||
e.by = user
|
||||
e.type = "changed_action_announcement"
|
||||
e.desc = "WG action text was changed"
|
||||
e.text = "To: ietf-announce@ietf.org\n"
|
||||
e.text += "Subject: WG Action: %s (%s)\n" % (wg.name, wg.acronym)
|
||||
e.text += "The %s (%s) working group " % (wg.name, wg.acronym)
|
||||
if wg.parent:
|
||||
e.text += "in the %s " % wg.parent.name
|
||||
e.text += "of the IETF has been "
|
||||
if wg.state_id == "proposed":
|
||||
e.text += "proposed"
|
||||
else:
|
||||
e.text += " rechartered"
|
||||
e.text += ". \nFor additional information, please contact the Area Directors or the working group Chairs."
|
||||
e.save()
|
||||
return e
|
||||
|
||||
def default_review_text(wg, charter, user):
|
||||
e = WriteupDocEvent(doc=charter, by=user)
|
||||
e.by = user
|
||||
e.type = "changed_review_announcement"
|
||||
e.desc = "WG review text was changed"
|
||||
e.text = "To: ietf-announce@ietf.org\n"
|
||||
e.text += "Subject: WG Review: %s (%s)\n" % (wg.name, wg.acronym)
|
||||
if wg.state_id == "proposed":
|
||||
e.text += "A charter"
|
||||
else:
|
||||
e.text += "A modified charter"
|
||||
e.text += " has been submitted for the %s (%s) working group \n" % (wg.name, wg.acronym)
|
||||
if wg.parent:
|
||||
e.text += "in the %s " % wg.parent.name
|
||||
e.text += "of the IETF. The charter is provided below for\n"
|
||||
e.text += "informational purposes only. Please send your comments to the\n"
|
||||
e.text += "IESG mailing list (iesg at ietf.org) within one week from today."
|
||||
e.save()
|
||||
return e
|
||||
|
||||
BALLOT_CHOICES = (("yes", "Yes"),
|
||||
("no", "No"),
|
||||
("block", "Block"),
|
||||
("abstain", "Abstain"),
|
||||
("", "No Record"),
|
||||
)
|
||||
|
||||
def position_to_ballot_choice(position):
|
||||
for v, label in BALLOT_CHOICES:
|
||||
if v and getattr(position, v):
|
||||
return v
|
||||
return ""
|
||||
|
||||
def position_label(position_value):
|
||||
return dict(BALLOT_CHOICES).get(position_value, "")
|
||||
|
||||
class EditPositionForm(forms.Form):
|
||||
position = forms.ModelChoiceField(queryset=GroupBallotPositionName.objects.all(), widget=forms.RadioSelect, initial="norecord", required=True)
|
||||
block_comment = forms.CharField(required=False, label="Blocking comment", widget=forms.Textarea)
|
||||
comment = forms.CharField(required=False, widget=forms.Textarea)
|
||||
return_to_url = forms.CharField(required=False, widget=forms.HiddenInput)
|
||||
|
||||
def clean_blocking(self):
|
||||
entered_blocking = self.cleaned_data["block_comment"]
|
||||
entered_pos = self.cleaned_data["position"]
|
||||
if entered_pos.slug == "block" and not entered_blocking:
|
||||
raise forms.ValidationError("You must enter a non-empty blocking comment")
|
||||
return entered_blocking
|
||||
|
||||
@group_required('Area_Director','Secretariat')
|
||||
def edit_position(request, name):
|
||||
"""Vote and edit comments on Charter as Area Director."""
|
||||
try:
|
||||
wg = Group.objects.get(acronym=name)
|
||||
except ObjectDoesNotExist:
|
||||
wglist = GroupHistory.objects.filter(acronym=name)
|
||||
if wglist:
|
||||
return redirect('wg_edit_position', name=wglist[0].group.acronym)
|
||||
else:
|
||||
raise Http404
|
||||
|
||||
charter = set_or_create_charter(wg)
|
||||
started_process = charter.latest_event(type="started_iesg_process")
|
||||
if not started_process:
|
||||
raise Http404
|
||||
|
||||
ad = login = request.user.get_profile()
|
||||
|
||||
if 'HTTP_REFERER' in request.META:
|
||||
return_to_url = request.META['HTTP_REFERER']
|
||||
else:
|
||||
return_to_url = charter.get_absolute_url()
|
||||
|
||||
# if we're in the Secretariat, we can select an AD to act as stand-in for
|
||||
if not has_role(request.user, "Area Director"):
|
||||
ad_id = request.GET.get('ad')
|
||||
if not ad_id:
|
||||
raise Http404()
|
||||
from person.models import Person
|
||||
ad = get_object_or_404(Person, pk=ad_id)
|
||||
|
||||
old_pos = charter.latest_event(GroupBallotPositionDocEvent, type="changed_ballot_position", ad=ad, time__gte=started_process.time)
|
||||
|
||||
if request.method == 'POST':
|
||||
form = EditPositionForm(request.POST)
|
||||
if form.is_valid():
|
||||
|
||||
# save the vote
|
||||
clean = form.cleaned_data
|
||||
|
||||
if clean['return_to_url']:
|
||||
return_to_url = clean['return_to_url']
|
||||
|
||||
pos = GroupBallotPositionDocEvent(doc=charter, by=login)
|
||||
pos.type = "changed_ballot_position"
|
||||
pos.ad = ad
|
||||
pos.pos = clean["position"]
|
||||
pos.comment = clean["comment"].strip()
|
||||
pos.comment_time = old_pos.comment_time if old_pos else None
|
||||
pos.block_comment = clean["block_comment"].strip() if pos.pos_id == "block" else ""
|
||||
pos.block_comment_time = old_pos.block_comment_time if old_pos else None
|
||||
|
||||
changes = []
|
||||
added_events = []
|
||||
# possibly add discuss/comment comments to history trail
|
||||
# so it's easy to see
|
||||
old_comment = old_pos.comment if old_pos else ""
|
||||
if pos.comment != old_comment:
|
||||
pos.comment_time = pos.time
|
||||
changes.append("comment")
|
||||
|
||||
if pos.comment:
|
||||
e = DocEvent(doc=charter)
|
||||
e.by = ad # otherwise we can't see who's saying it
|
||||
e.type = "added_comment"
|
||||
e.desc = "[Ballot comment]\n" + pos.comment
|
||||
added_events.append(e)
|
||||
|
||||
old_block_comment = old_pos.block_comment if old_pos else ""
|
||||
if pos.block_comment != old_block_comment:
|
||||
pos.block_comment_time = pos.time
|
||||
changes.append("block_comment")
|
||||
|
||||
if pos.block_comment:
|
||||
e = DocEvent(doc=charter, by=login)
|
||||
e.by = ad # otherwise we can't see who's saying it
|
||||
e.type = "added_comment"
|
||||
e.desc = "[Ballot blocking comment]\n" + pos.block_comment
|
||||
added_events.append(e)
|
||||
|
||||
# figure out a description
|
||||
if not old_pos and pos.pos.slug != "norecord":
|
||||
pos.desc = u"[Ballot Position Update] New position, %s, has been recorded for %s" % (pos.pos.name, pos.ad.name)
|
||||
elif old_pos and pos.pos != old_pos.pos:
|
||||
pos.desc = "[Ballot Position Update] Position for %s has been changed to %s from %s" % (pos.ad.name, pos.pos.name, old_pos.pos.name)
|
||||
|
||||
if not pos.desc and changes:
|
||||
pos.desc = u"Ballot %s text updated for %s" % (u" and ".join(changes), ad.name)
|
||||
|
||||
# only add new event if we actually got a change
|
||||
if pos.desc:
|
||||
if login != ad:
|
||||
pos.desc += u" by %s" % login.name
|
||||
|
||||
pos.save()
|
||||
|
||||
for e in added_events:
|
||||
e.save() # save them after the position is saved to get later id
|
||||
|
||||
charter.time = pos.time
|
||||
charter.save()
|
||||
|
||||
if request.POST.get("send_mail"):
|
||||
qstr = "?return_to_url=%s" % return_to_url
|
||||
if request.GET.get('ad'):
|
||||
qstr += "&ad=%s" % request.GET.get('ad')
|
||||
return HttpResponseRedirect(urlreverse("wg_send_ballot_comment", kwargs=dict(name=wg.acronym)) + qstr)
|
||||
else:
|
||||
return HttpResponseRedirect(return_to_url)
|
||||
else:
|
||||
initial = {}
|
||||
if old_pos:
|
||||
initial['position'] = old_pos.pos.slug
|
||||
initial['block_comment'] = old_pos.block_comment
|
||||
initial['comment'] = old_pos.comment
|
||||
|
||||
if return_to_url:
|
||||
initial['return_to_url'] = return_to_url
|
||||
|
||||
form = EditPositionForm(initial=initial)
|
||||
|
||||
return render_to_response('wgrecord/edit_position.html',
|
||||
dict(charter=charter,
|
||||
wg=wg,
|
||||
form=form,
|
||||
ad=ad,
|
||||
return_to_url=return_to_url,
|
||||
old_pos=old_pos,
|
||||
),
|
||||
context_instance=RequestContext(request))
|
||||
|
||||
@group_required('Area_Director','Secretariat')
|
||||
def send_ballot_comment(request, name):
|
||||
"""Email Charter ballot comment for area director."""
|
||||
try:
|
||||
wg = Group.objects.get(acronym=name)
|
||||
except ObjectDoesNotExist:
|
||||
wglist = GroupHistory.objects.filter(acronym=name)
|
||||
if wglist:
|
||||
return redirect('wg_send_ballot_comment', name=wglist[0].group.acronym)
|
||||
else:
|
||||
raise Http404
|
||||
|
||||
charter = set_or_create_charter(wg)
|
||||
started_process = charter.latest_event(type="started_iesg_process")
|
||||
if not started_process:
|
||||
raise Http404()
|
||||
|
||||
ad = login = request.user.get_profile()
|
||||
|
||||
return_to_url = request.GET.get('return_to_url')
|
||||
if not return_to_url:
|
||||
return_to_url = charter.get_absolute_url()
|
||||
|
||||
if 'HTTP_REFERER' in request.META:
|
||||
back_url = request.META['HTTP_REFERER']
|
||||
else:
|
||||
back_url = charter.get_absolute_url()
|
||||
|
||||
# if we're in the Secretariat, we can select an AD to act as stand-in for
|
||||
if not has_role(request.user, "Area Director"):
|
||||
ad_id = request.GET.get('ad')
|
||||
if not ad_id:
|
||||
raise Http404()
|
||||
from person.models import Person
|
||||
ad = get_object_or_404(Person, pk=ad_id)
|
||||
|
||||
pos = charter.latest_event(GroupBallotPositionDocEvent, type="changed_ballot_position", ad=ad, time__gte=started_process.time)
|
||||
if not pos:
|
||||
raise Http404()
|
||||
|
||||
subj = []
|
||||
d = ""
|
||||
if pos.pos_id == "block" and pos.block_comment:
|
||||
d = pos.block_comment
|
||||
subj.append("BLOCKING COMMENT")
|
||||
c = ""
|
||||
if pos.comment:
|
||||
c = pos.comment
|
||||
subj.append("COMMENT")
|
||||
|
||||
ad_name_genitive = ad.name + "'" if ad.name.endswith('s') else ad.name + "'s"
|
||||
subject = "%s %s on %s" % (ad_name_genitive, pos.pos.name if pos.pos else "No Position", charter.name + "-" + charter.rev)
|
||||
if subj:
|
||||
subject += ": (with %s)" % " and ".join(subj)
|
||||
|
||||
body = render_to_string("wgrecord/ballot_comment_mail.txt",
|
||||
dict(block_comment=d, comment=c, ad=ad.name, charter=charter, pos=pos.pos))
|
||||
frm = ad.formatted_email()
|
||||
to = "The IESG <iesg@ietf.org>"
|
||||
|
||||
if request.method == 'POST':
|
||||
cc = [x.strip() for x in request.POST.get("cc", "").split(',') if x.strip()]
|
||||
send_mail_text(request, to, frm, subject, body, cc=", ".join(cc))
|
||||
|
||||
return HttpResponseRedirect(return_to_url)
|
||||
|
||||
return render_to_response('wgrecord/send_ballot_comment.html',
|
||||
dict(charter=charter,
|
||||
subject=subject,
|
||||
body=body,
|
||||
frm=frm,
|
||||
to=to,
|
||||
ad=ad,
|
||||
can_send=d or c,
|
||||
back_url=back_url,
|
||||
),
|
||||
context_instance=RequestContext(request))
|
||||
|
||||
class AnnouncementTextForm(forms.Form):
|
||||
announcement_text = forms.CharField(widget=forms.Textarea, required=True)
|
||||
|
||||
def clean_announcement_text(self):
|
||||
return self.cleaned_data["announcement_text"].replace("\r", "")
|
||||
|
||||
@group_required('Area_Director','Secretariat')
|
||||
def announcement_text(request, name, ann):
|
||||
"""Editing of announcement text"""
|
||||
try:
|
||||
wg = Group.objects.get(acronym=name)
|
||||
except ObjectDoesNotExist:
|
||||
wglist = GroupHistory.objects.filter(acronym=name)
|
||||
if wglist:
|
||||
return redirect('wg_announcement_text', name=wglist[0].group.acronym)
|
||||
else:
|
||||
raise Http404
|
||||
|
||||
charter = set_or_create_charter(wg)
|
||||
|
||||
login = request.user.get_profile()
|
||||
|
||||
if ann == "action":
|
||||
existing = charter.latest_event(WriteupDocEvent, type="changed_action_announcement")
|
||||
elif ann == "review":
|
||||
existing = charter.latest_event(WriteupDocEvent, type="changed_review_announcement")
|
||||
if not existing:
|
||||
if ann == "action":
|
||||
existing = default_action_text(wg, charter, login)
|
||||
elif ann == "review":
|
||||
existing = default_review_text(wg, charter, login)
|
||||
|
||||
form = AnnouncementTextForm(initial=dict(announcement_text=existing.text))
|
||||
|
||||
if request.method == 'POST':
|
||||
form = AnnouncementTextForm(request.POST)
|
||||
if form.is_valid():
|
||||
t = form.cleaned_data['announcement_text']
|
||||
if t != existing.text:
|
||||
e = WriteupDocEvent(doc=charter, by=login)
|
||||
e.by = login
|
||||
e.type = "changed_%s_announcement" % ann
|
||||
e.desc = "WG %s text was changed" % ann
|
||||
e.text = t
|
||||
e.save()
|
||||
|
||||
charter.time = e.time
|
||||
charter.save()
|
||||
return redirect('wg_view_record', name=wg.acronym)
|
||||
return render_to_response('wgrecord/announcement_text.html',
|
||||
dict(charter=charter,
|
||||
announcement=ann,
|
||||
back_url=charter.get_absolute_url(),
|
||||
announcement_text_form=form,
|
||||
),
|
||||
context_instance=RequestContext(request))
|
||||
|
||||
@group_required('Secretariat')
|
||||
def approve_ballot(request, name):
|
||||
"""Approve ballot, changing state, copying charter"""
|
||||
try:
|
||||
wg = Group.objects.get(acronym=name)
|
||||
except ObjectDoesNotExist:
|
||||
wglist = GroupHistory.objects.filter(acronym=name)
|
||||
if wglist:
|
||||
return redirect('wg_approve_ballot', name=wglist[0].group.acronym)
|
||||
else:
|
||||
raise Http404
|
||||
|
||||
charter = set_or_create_charter(wg)
|
||||
|
||||
login = request.user.get_profile()
|
||||
|
||||
e = charter.latest_event(WriteupDocEvent, type="changed_action_announcement")
|
||||
if not e:
|
||||
announcement = default_action_text(wg, charter, login).text
|
||||
else:
|
||||
announcement = e.text
|
||||
|
||||
if request.method == 'POST':
|
||||
new_state = GroupStateName.objects.get(slug="active")
|
||||
new_charter_state = CharterDocStateName.objects.get(slug="approved")
|
||||
|
||||
save_charter_in_history(charter)
|
||||
save_group_in_history(wg)
|
||||
|
||||
prev_state = wg.state
|
||||
prev_charter_state = charter.charter_state
|
||||
wg.state = new_state
|
||||
charter.charter_state = new_charter_state
|
||||
|
||||
e = DocEvent(doc=charter, by=login)
|
||||
e.type = "iesg_approved"
|
||||
e.desc = "IESG has approved the charter"
|
||||
|
||||
e.save()
|
||||
|
||||
change_description = e.desc + " and WG state has been changed to %s" % new_state.name
|
||||
|
||||
e = log_state_changed(request, charter, login, prev_state)
|
||||
|
||||
wg.time = e.time
|
||||
wg.save()
|
||||
|
||||
ch = get_charter_for_revision(wg.charter, wg.charter.rev)
|
||||
|
||||
filename = os.path.join(charter.get_file_path(), ch.name+"-"+ch.rev+".txt")
|
||||
if not hasattr(settings, 'DONT_COPY_CHARTER_ON_APPROVE') or not settings.DONT_COPY_CHARTER_ON_APPROVE:
|
||||
try:
|
||||
source = open(filename, 'rb')
|
||||
raw_content = source.read()
|
||||
|
||||
new_filename = os.path.join(charter.get_file_path(), 'charter-ietf-%s-%s.txt' % (wg.acronym, next_approved_revision(ch.rev)))
|
||||
destination = open(new_filename, 'wb+')
|
||||
destination.write(raw_content)
|
||||
destination.close()
|
||||
except IOError:
|
||||
raise Http404("Charter text %s" % (filename))
|
||||
|
||||
charter.rev = next_approved_revision(charter.rev)
|
||||
charter.save()
|
||||
|
||||
email_secretariat(request, wg, "state-%s" % charter.charter_state_id, change_description)
|
||||
|
||||
# send announcement
|
||||
send_mail_preformatted(request, announcement)
|
||||
|
||||
return HttpResponseRedirect(charter.get_absolute_url())
|
||||
|
||||
return render_to_response('wgrecord/approve_ballot.html',
|
||||
dict(charter=charter,
|
||||
announcement=announcement,
|
||||
wg=wg),
|
||||
context_instance=RequestContext(request))
|
||||
|
|
@ -1,492 +0,0 @@
|
|||
# Copyright The IETF Trust 2011, All Rights Reserved
|
||||
|
||||
import re, os, string
|
||||
from datetime import datetime, date, time, timedelta
|
||||
from django.shortcuts import render_to_response, get_object_or_404, redirect
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.template import RequestContext
|
||||
from django import forms
|
||||
from django.forms.util import ErrorList
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
|
||||
from utils import log_state_changed, log_group_state_changed, log_info_changed, update_telechat, add_wg_comment, set_or_create_charter, save_charter_in_history
|
||||
from mails import email_secretariat
|
||||
from ietf.ietfauth.decorators import group_required
|
||||
from ietf.iesg.models import TelechatDates
|
||||
|
||||
from doc.models import Document, DocHistory, DocAlias, DocEvent, TelechatDocEvent, InitialReviewDocEvent
|
||||
from name.models import CharterDocStateName, GroupStateName, GroupTypeName, DocTypeName, RoleName
|
||||
from person.models import Person, Email
|
||||
from group.models import Group, GroupEvent, GroupHistory, GroupURL, Role, RoleHistory, save_group_in_history
|
||||
|
||||
from views_search import json_emails
|
||||
|
||||
class ChangeStateForm(forms.Form):
|
||||
charter_state = forms.ModelChoiceField(CharterDocStateName.objects.all(), label="Charter state", empty_label=None, required=False)
|
||||
confirm_state = forms.BooleanField(widget=forms.HiddenInput, required=False, initial=True)
|
||||
initial_time = forms.IntegerField(initial=0, label="Review time", help_text="(in weeks)", required=False)
|
||||
message = forms.CharField(widget=forms.Textarea, help_text="Message to the secretariat", required=False)
|
||||
comment = forms.CharField(widget=forms.Textarea, help_text="Comment for the WG history", required=False)
|
||||
def __init__(self, *args, **kwargs):
|
||||
if 'queryset' in kwargs:
|
||||
qs = kwargs.pop('queryset')
|
||||
else:
|
||||
qs = None
|
||||
if 'hide' in kwargs:
|
||||
self.hide = kwargs.pop('hide')
|
||||
else:
|
||||
self.hide = None
|
||||
super(ChangeStateForm, self).__init__(*args, **kwargs)
|
||||
if qs:
|
||||
self.fields['charter_state'].queryset = qs
|
||||
# hide requested fields
|
||||
if self.hide:
|
||||
for f in self.hide:
|
||||
self.fields[f].widget = forms.HiddenInput
|
||||
|
||||
@group_required('Area_Director','Secretariat')
|
||||
def change_state(request, name, option=None):
|
||||
"""Change state of WG and charter, notifying parties as necessary
|
||||
and logging the change as a comment."""
|
||||
# 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
|
||||
|
||||
initial_review = charter.latest_event(InitialReviewDocEvent, type="initial_review")
|
||||
|
||||
login = request.user.get_profile()
|
||||
|
||||
if request.method == 'POST':
|
||||
form = ChangeStateForm(request.POST)
|
||||
if form.is_valid():
|
||||
if initial_review and form.cleaned_data['charter_state'] 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:
|
||||
if option == "initcharter" or option == "recharter":
|
||||
charter_state=CharterDocStateName.objects.get(slug="infrev")
|
||||
elif option == "abandon":
|
||||
if wg.state_id == "proposed":
|
||||
charter_state = CharterDocStateName.objects.get(slug="notrev")
|
||||
else:
|
||||
charter_state = CharterDocStateName.objects.get(slug="approved")
|
||||
else:
|
||||
charter_state = form.cleaned_data['charter_state']
|
||||
|
||||
comment = form.cleaned_data['comment']
|
||||
message = form.cleaned_data['message']
|
||||
|
||||
change = False
|
||||
if charter:
|
||||
# The WG has a charter
|
||||
if charter_state != charter.charter_state:
|
||||
# Charter state changed
|
||||
change = True
|
||||
save_charter_in_history(charter)
|
||||
|
||||
prev = charter.charter_state
|
||||
charter.charter_state = charter_state
|
||||
|
||||
e = log_state_changed(request, charter, login, prev, comment)
|
||||
charter.time = datetime.now()
|
||||
charter.save()
|
||||
else:
|
||||
# WG does not yet have a charter
|
||||
if charter_state != "infrev":
|
||||
# This is an error
|
||||
raise Http404
|
||||
|
||||
if change:
|
||||
if charter:
|
||||
messages = {}
|
||||
messages['extrev'] = "The WG has been set to External review by %s. Please schedule discussion for the next IESG telechat." % login.name
|
||||
|
||||
if message != "":
|
||||
email_secretariat(request, wg, "state-%s" % charter.charter_state_id, message)
|
||||
if charter.charter_state_id == "extrev":
|
||||
email_secretariat(request, wg, "state-%s" % charter.charter_state_id, messages['extrev'])
|
||||
|
||||
if charter_state.slug == "infrev":
|
||||
e = DocEvent()
|
||||
e.type = "started_iesg_process"
|
||||
e.by = login
|
||||
e.doc = charter
|
||||
e.desc = "IESG process started in state <b>%s</b>" % charter.charter_state.name
|
||||
e.save()
|
||||
|
||||
if 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
|
||||
e.doc = charter
|
||||
e.expires = datetime.now() + timedelta(weeks=form.cleaned_data["initial_time"])
|
||||
e.desc = "Initial review time expires %s" % e.expires.strftime("%Y-%m-%d")
|
||||
e.save()
|
||||
|
||||
return redirect('wg_view_record', name=wg.acronym)
|
||||
else:
|
||||
if option == "recharter":
|
||||
hide = ['charter_state']
|
||||
init = dict(initial_time=1, message="%s has initiated a recharter effort on the WG %s (%s)" % (login.name, wg.name, wg.acronym))
|
||||
elif option == "initcharter":
|
||||
hide = ['charter_state']
|
||||
init = dict(initial_time=1, message="%s has initiated chartering of the proposed WG %s (%s)" % (login.name, wg.name, wg.acronym))
|
||||
elif option == "abandon":
|
||||
hide = ['initial_time', 'charter_state']
|
||||
init = dict(message="%s has abandoned the chartering effort on the WG %s (%s)" % (login.name, wg.name, wg.acronym))
|
||||
else:
|
||||
hide = ['initial_time']
|
||||
init = dict(charter_state=wg.charter.charter_state_id, state=wg.state_id)
|
||||
states = CharterDocStateName.objects.filter(slug__in=["infrev", "intrev", "extrev", "iesgrev"])
|
||||
form = ChangeStateForm(queryset=states, hide=hide, initial=init)
|
||||
|
||||
group_hists = GroupHistory.objects.filter(group=wg).exclude(state=wg.state).order_by("-time")[:1]
|
||||
if charter:
|
||||
charter_hists = DocHistory.objects.filter(doc__name=charter.name).exclude(charter_state=charter.charter_state).order_by("-time")[:1]
|
||||
if charter_hists:
|
||||
prev_charter_state = charter_hists[0].charter_state
|
||||
else:
|
||||
prev_charter_state = None
|
||||
else:
|
||||
prev_charter_state = None
|
||||
|
||||
return render_to_response('wgrecord/change_state.html',
|
||||
dict(form=form,
|
||||
wg=wg,
|
||||
login=login,
|
||||
option=option,
|
||||
prev_charter_state=prev_charter_state),
|
||||
context_instance=RequestContext(request))
|
||||
|
||||
class EditInfoForm(forms.Form):
|
||||
name = forms.CharField(max_length=255, label="WG Name", required=True)
|
||||
acronym = forms.CharField(max_length=8, label="WG Acronym", required=True)
|
||||
chairs = forms.CharField(max_length=255, label="WG Chairs", help_text="Type in a name", required=False)
|
||||
secretaries = forms.CharField(max_length=255, label="WG Secretaries", help_text="Type in a name", required=False)
|
||||
techadv = forms.CharField(max_length=255, label="WG Technical Advisors", help_text="Type in a name", required=False)
|
||||
ad = forms.ModelChoiceField(Person.objects.filter(email__role__name__in=("ad", "ex-ad")).order_by('email__role__name', 'name'), label="Shepherding AD", empty_label="-", required=False)
|
||||
parent = forms.ModelChoiceField(Group.objects.filter(type="area", state="active").order_by('name'), label="IETF Area", empty_label="-", required=False)
|
||||
list_email = forms.CharField(max_length=64, required=False)
|
||||
list_subscribe = forms.CharField(max_length=255, required=False)
|
||||
list_archive = forms.CharField(max_length=255, required=False)
|
||||
urls = forms.CharField(widget=forms.Textarea, label="Additional URLs", help_text="Format: http://site/url (optional description). Separate by newline.", required=False)
|
||||
telechat_date = forms.TypedChoiceField(coerce=lambda x: datetime.strptime(x, '%Y-%m-%d').date(), empty_value=None, required=False)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.cur_acronym = kwargs.pop('cur_acronym')
|
||||
if 'hide' in kwargs:
|
||||
self.hide = kwargs.pop('hide')
|
||||
else:
|
||||
self.hide = None
|
||||
super(self.__class__, self).__init__(*args, **kwargs)
|
||||
|
||||
# hide requested fields
|
||||
if self.hide:
|
||||
for f in self.hide:
|
||||
self.fields[f].widget = forms.HiddenInput
|
||||
|
||||
# fix up ad field
|
||||
choices = self.fields['ad'].choices
|
||||
ex_ads = dict((e.pk, e) for e in Person.objects.filter(email__role__name="ex-ad").distinct())
|
||||
|
||||
# remove old ones
|
||||
self.fields['ad'].choices = [t for t in choices if t[0] not in ex_ads]
|
||||
|
||||
# telechat choices
|
||||
dates = TelechatDates.objects.all()[0].dates()
|
||||
if 'telechat_date' in kwargs['initial']:
|
||||
init = kwargs['initial']['telechat_date']
|
||||
if init and init not in dates:
|
||||
dates.insert(0, init)
|
||||
|
||||
choices = [("", "(not on agenda)")]
|
||||
for d in dates:
|
||||
choices.append((d, d.strftime("%Y-%m-%d")))
|
||||
|
||||
self.fields['telechat_date'].choices = choices
|
||||
|
||||
def clean_acronym(self):
|
||||
acronym = self.cleaned_data['acronym']
|
||||
if self.cur_acronym and acronym != self.cur_acronym:
|
||||
try:
|
||||
Group.objects.get(acronym=acronym)
|
||||
except ObjectDoesNotExist:
|
||||
gh = GroupHistory.objects.filter(acronym=acronym)
|
||||
if gh:
|
||||
raise forms.ValidationError("Acronym used in a previous WG. Please pick another.")
|
||||
else:
|
||||
return acronym
|
||||
raise forms.ValidationError("Acronym used in a previous WG. Please pick another.")
|
||||
return acronym
|
||||
|
||||
def format_urls(set, fs="\n"):
|
||||
ostr = ""
|
||||
for i,x in enumerate(set):
|
||||
if i != 0:
|
||||
ostr += fs
|
||||
if x.name:
|
||||
ostr += x.url + " (" + x.name + ")"
|
||||
else:
|
||||
ostr += x.url
|
||||
|
||||
return ostr
|
||||
|
||||
@group_required('Area_Director','Secretariat')
|
||||
def edit_info(request, name=None):
|
||||
"""Edit or create a WG, notifying parties as
|
||||
necessary and logging changes as group events."""
|
||||
import sys
|
||||
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
|
||||
new_wg = True
|
||||
|
||||
login = request.user.get_profile()
|
||||
|
||||
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), cur_acronym=wg.acronym if wg else None)
|
||||
if form.is_valid():
|
||||
r = form.cleaned_data
|
||||
if not new_wg:
|
||||
gh = save_group_in_history(wg)
|
||||
else:
|
||||
# Create WG
|
||||
wg = Group(name=r["name"],
|
||||
acronym=r["acronym"],
|
||||
type=GroupTypeName.objects.get(name="WG"),
|
||||
state=GroupStateName.objects.get(name="Proposed"))
|
||||
wg.save()
|
||||
|
||||
e = GroupEvent(group=wg, type="proposed")
|
||||
e.time = datetime.now()
|
||||
e.by = login
|
||||
e.desc = "Proposed group"
|
||||
e.save()
|
||||
if not wg.charter:
|
||||
# Create adjoined charter
|
||||
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()
|
||||
e.by = login
|
||||
e.desc = "Started IESG process on charter"
|
||||
e.save()
|
||||
|
||||
changes = []
|
||||
|
||||
def desc(attr, new, old):
|
||||
entry = "%(attr)s has been changed to <b>%(new)s</b> from <b>%(old)s</b>"
|
||||
if new_wg:
|
||||
entry = "%(attr)s has been changed to <b>%(new)s</b>"
|
||||
|
||||
return entry % dict(attr=attr, new=new, old=old)
|
||||
|
||||
def get_model_fields_as_dict(obj):
|
||||
return dict((field.name, getattr(obj, field.name))
|
||||
for field in obj._meta.fields
|
||||
if field is not obj._meta.pk)
|
||||
|
||||
def diff(attr, name):
|
||||
v = getattr(wg, attr)
|
||||
if r[attr] != v:
|
||||
changes.append(desc(name, r[attr], v))
|
||||
setattr(wg, attr, r[attr])
|
||||
if attr == "acronym":
|
||||
c = wg.charter
|
||||
save_charter_in_history(c)
|
||||
# and add a DocAlias
|
||||
DocAlias.objects.create(
|
||||
name = "charter-ietf-%s" % r['acronym'],
|
||||
document = charter
|
||||
)
|
||||
|
||||
# update the attributes, keeping track of what we're doing
|
||||
diff('name', "Name")
|
||||
diff('acronym', "Acronym")
|
||||
diff('ad', "Shepherding AD")
|
||||
diff('parent', "IETF Area")
|
||||
diff('list_email', "Mailing list email")
|
||||
diff('list_subscribe', "Mailing list subscribe address")
|
||||
diff('list_archive', "Mailing list archive")
|
||||
|
||||
def get_sorted_string(attr, splitter):
|
||||
if splitter == '\n':
|
||||
out = sorted(r[attr].splitlines())
|
||||
else:
|
||||
out = sorted(r[attr].split(splitter))
|
||||
if out == ['']:
|
||||
out = []
|
||||
return out
|
||||
|
||||
# update roles
|
||||
for attr_role in [('chairs', 'Chair'), ('secretaries', 'Secretary'), ('techadv', 'Tech Advisor')]:
|
||||
attr = attr_role[0]
|
||||
rname = attr_role[1]
|
||||
new = get_sorted_string(attr, ",")
|
||||
old = [x.email.address for x in wg.role_set.filter(name__name=rname).order_by('email__address')]
|
||||
if new != old:
|
||||
changes.append(desc(rname,
|
||||
",".join([Person.objects.get(email__address=x).name for x in new]),
|
||||
",".join([Person.objects.get(email__address=x).name for x in old])))
|
||||
# Remove old roles and save them in history
|
||||
for role in wg.role_set.filter(name__name=rname):
|
||||
role.delete()
|
||||
# Add new ones
|
||||
rolename = RoleName.objects.get(name=rname)
|
||||
for e in new:
|
||||
email = Email.objects.get(address=e)
|
||||
role = Role(name=rolename, email=email, group=wg)
|
||||
role.save()
|
||||
|
||||
# update urls
|
||||
new_urls = get_sorted_string('urls', '\n')
|
||||
old_urls = format_urls(wg.groupurl_set.order_by('url'), ", ")
|
||||
if ", ".join(new_urls) != old_urls:
|
||||
changes.append(desc('urls', ", ".join(new_urls), old_urls))
|
||||
# Remove old urls
|
||||
for u in wg.groupurl_set.all():
|
||||
u.delete()
|
||||
# Add new ones
|
||||
for u in [u for u in new_urls if u != ""]:
|
||||
m = re.search('(?P<url>[\w\d:#@%/;$()~_?\+-=\\\.&]+)( \((?P<name>.+)\))?', u)
|
||||
if m:
|
||||
if m.group('name'):
|
||||
url = GroupURL(url=m.group('url'), name=m.group('name'), group=wg)
|
||||
else:
|
||||
url = GroupURL(url=m.group('url'), name='', group=wg)
|
||||
url.save()
|
||||
|
||||
wg.time = datetime.now()
|
||||
|
||||
if changes and not new_wg:
|
||||
for c in changes:
|
||||
log_info_changed(request, wg, login, c)
|
||||
|
||||
update_telechat(request, wg.charter, login, r['telechat_date'])
|
||||
|
||||
wg.save()
|
||||
if new_wg:
|
||||
return redirect('wg_startstop_process', name=wg.acronym, option="initcharter")
|
||||
else:
|
||||
return redirect('wg_view_record', name=wg.acronym)
|
||||
else: # form.is_valid()
|
||||
if not new_wg:
|
||||
init = dict(name=wg.name,
|
||||
acronym=wg.acronym,
|
||||
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=format_urls(wg.groupurl_set.all()),
|
||||
telechat_date=initial_telechat_date,
|
||||
)
|
||||
hide = None
|
||||
else:
|
||||
init = dict(ad=login.id,
|
||||
)
|
||||
hide = ['chairs', 'techadv', 'list_email', 'list_subscribe', 'list_archive', 'urls', 'telechat_date']
|
||||
form = EditInfoForm(initial=init, cur_acronym=wg.acronym if wg else None, hide=hide)
|
||||
|
||||
return render_to_response('wgrecord/edit_info.html',
|
||||
dict(wg=wg,
|
||||
form=form,
|
||||
user=request.user,
|
||||
login=login),
|
||||
context_instance=RequestContext(request))
|
||||
|
||||
class ConcludeForm(forms.Form):
|
||||
instructions = forms.CharField(widget=forms.Textarea, required=True)
|
||||
|
||||
@group_required('Area_Director','Secretariat')
|
||||
def conclude(request, name):
|
||||
"""Request the closing of a WG, prompting for instructions."""
|
||||
try:
|
||||
wg = Group.objects.get(acronym=name)
|
||||
except ObjectDoesNotExist:
|
||||
wglist = GroupHistory.objects.filter(acronym=name)
|
||||
if wglist:
|
||||
return redirect('wg_conclude', name=wglist[0].group.acronym)
|
||||
else:
|
||||
raise Http404
|
||||
|
||||
login = request.user.get_profile()
|
||||
|
||||
# if state != wg.state:
|
||||
# # WG state changed
|
||||
# change = True
|
||||
# save_group_in_history(wg)
|
||||
|
||||
# prev = wg.state
|
||||
# wg.state = state
|
||||
|
||||
# ge = log_group_state_changed(request, wg, login, comment)
|
||||
|
||||
# wg.save()
|
||||
|
||||
if request.method == 'POST':
|
||||
form = ConcludeForm(request.POST)
|
||||
if form.is_valid():
|
||||
instructions = form.cleaned_data['instructions']
|
||||
|
||||
email_secretariat(request, wg, "conclude", instructions)
|
||||
|
||||
return redirect('wg_view_record', name=wg.acronym)
|
||||
else:
|
||||
form = ConcludeForm()
|
||||
|
||||
return render_to_response('wgrecord/conclude.html',
|
||||
dict(form=form,
|
||||
wg=wg),
|
||||
context_instance=RequestContext(request))
|
||||
|
||||
class AddCommentForm(forms.Form):
|
||||
comment = forms.CharField(required=True, widget=forms.Textarea)
|
||||
|
||||
@group_required('Area_Director','Secretariat')
|
||||
def add_comment(request, name):
|
||||
"""Add comment to WG Record."""
|
||||
wg = get_object_or_404(Group, acronym=name)
|
||||
|
||||
login = request.user.get_profile()
|
||||
|
||||
if request.method == 'POST':
|
||||
form = AddCommentForm(request.POST)
|
||||
if form.is_valid():
|
||||
c = form.cleaned_data['comment']
|
||||
|
||||
add_wg_comment(request, wg, c)
|
||||
|
||||
#email_owner(request, doc, doc.ad, login,
|
||||
# "A new comment added by %s" % login.name)
|
||||
return redirect('wg_view_record', name=wg.acronym)
|
||||
else:
|
||||
form = AddCommentForm()
|
||||
|
||||
return render_to_response('wgrecord/add_comment.html',
|
||||
dict(wg=wg,
|
||||
form=form),
|
||||
context_instance=RequestContext(request))
|
||||
|
|
@ -1,238 +0,0 @@
|
|||
# Copyright The IETF Trust 2011, All Rights Reserved
|
||||
|
||||
import re, os
|
||||
from datetime import datetime, time
|
||||
|
||||
from django.http import HttpResponse, Http404
|
||||
from django.shortcuts import render_to_response, get_object_or_404, redirect
|
||||
from django.template import RequestContext
|
||||
from django.template.defaultfilters import truncatewords_html
|
||||
from django.utils import simplejson as json
|
||||
from django.utils.decorators import decorator_from_middleware
|
||||
from django.middleware.gzip import GZipMiddleware
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
from doc.models import GroupBallotPositionDocEvent, WriteupDocEvent
|
||||
from group.models import Group, GroupHistory
|
||||
from person.models import Person
|
||||
from wgrecord import markup_txt
|
||||
from django.conf import settings
|
||||
|
||||
from wgrecord.utils import *
|
||||
from ietf.utils.history import find_history_active_at
|
||||
from ietf.idtracker.templatetags.ietf_filters import format_textarea, fill
|
||||
|
||||
def _get_html(key, filename):
|
||||
f = None
|
||||
try:
|
||||
f = open(filename, 'rb')
|
||||
raw_content = f.read()
|
||||
except IOError:
|
||||
return "Error; cannot read ("+key+")"
|
||||
finally:
|
||||
if f:
|
||||
f.close()
|
||||
content = markup_txt.markup(raw_content)
|
||||
return content
|
||||
|
||||
@decorator_from_middleware(GZipMiddleware)
|
||||
def wg_main(request, name, rev, tab):
|
||||
if tab is None:
|
||||
tab = "charter"
|
||||
try:
|
||||
wg = Group.objects.get(acronym=name)
|
||||
except ObjectDoesNotExist:
|
||||
wglist = GroupHistory.objects.filter(acronym=name)
|
||||
if wglist:
|
||||
return redirect('wg_view_record', name=wglist[0].group.acronym)
|
||||
else:
|
||||
raise Http404
|
||||
|
||||
if not wg.charter:
|
||||
set_or_create_charter(wg)
|
||||
|
||||
if wg.charter.charter_state_id == "approved":
|
||||
active_rev = approved_revision(wg.charter.rev)
|
||||
else:
|
||||
active_rev = wg.charter.rev
|
||||
|
||||
if rev != None:
|
||||
ch = get_charter_for_revision(wg.charter, rev)
|
||||
gh = get_group_for_revision(wg, rev)
|
||||
else:
|
||||
ch = get_charter_for_revision(wg.charter, active_rev)
|
||||
gh = get_group_for_revision(wg, wg.charter.rev)
|
||||
|
||||
|
||||
info = {}
|
||||
|
||||
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 x.list_email != u'']))
|
||||
if prev_list_email != [u'']:
|
||||
info['prev_list_email'] = prev_list_email
|
||||
prev_list_subscribe = list(set([x.list_subscribe for x in wg.history_set.exclude(list_subscribe=wg.list_subscribe) if x.list_subscribe != u'']))
|
||||
if prev_list_subscribe != [u'']:
|
||||
info['prev_list_subscribe'] = prev_list_subscribe
|
||||
prev_list_archive = list(set([x.list_archive for x in wg.history_set.exclude(list_archive=wg.list_archive) if x.list_archive != u'']))
|
||||
if prev_list_archive != [u'']:
|
||||
info['prev_list_archive'] = prev_list_archive
|
||||
info['chairs'] = [x.email.person.name for x in wg.role_set.filter(name__slug="chair")]
|
||||
if hasattr(gh, 'rolehistory_set'):
|
||||
info['history_chairs'] = [x.email.person.name for x in gh.rolehistory_set.filter(name__slug="chair")]
|
||||
else:
|
||||
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 ch:
|
||||
file_path = wg.charter.get_file_path() # Get from wg.charter
|
||||
content = _get_html(
|
||||
"charter-ietf-"+str(gh.acronym)+"-"+str(ch.rev)+".txt",
|
||||
os.path.join(file_path, "charter-ietf-"+gh.acronym+"-"+ch.rev+".txt"))
|
||||
active_ads = list(Person.objects.filter(email__role__name="ad",
|
||||
email__role__group__type="area",
|
||||
email__role__group__state="active").distinct())
|
||||
started_process = wg.charter.latest_event(type="started_iesg_process")
|
||||
latest_positions = []
|
||||
no_record = []
|
||||
for p in active_ads:
|
||||
p_pos = list(GroupBallotPositionDocEvent.objects.filter(doc=wg.charter, ad=p).order_by("-time"))
|
||||
if p_pos != []:
|
||||
latest_positions.append(p_pos[0])
|
||||
else:
|
||||
no_record.append(p)
|
||||
|
||||
info['positions'] = latest_positions
|
||||
info['pos_yes'] = filter(lambda x: x.pos_id == "yes", latest_positions)
|
||||
info['pos_no'] = filter(lambda x: x.pos_id == "no", latest_positions)
|
||||
info['pos_block'] = filter(lambda x: x.pos_id == "block", latest_positions)
|
||||
info['pos_abstain'] = filter(lambda x: x.pos_id == "abstain", latest_positions)
|
||||
info['pos_no_record'] = no_record + [x.ad for x in latest_positions if x.pos_id == "norecord"]
|
||||
|
||||
# Get annoucement texts
|
||||
review_ann = wg.charter.latest_event(WriteupDocEvent, type="changed_review_announcement")
|
||||
info['review_text'] = review_ann.text if review_ann else ""
|
||||
action_ann = wg.charter.latest_event(WriteupDocEvent, type="changed_action_announcement")
|
||||
info['action_text'] = action_ann.text if action_ann else ""
|
||||
else:
|
||||
content = ""
|
||||
|
||||
versions = _get_versions(wg.charter) # Important: wg.charter not ch
|
||||
history = _get_history(wg)
|
||||
|
||||
if history:
|
||||
info['last_update'] = history[0]['date']
|
||||
|
||||
charter_text_url = wg.charter.get_txt_url()
|
||||
|
||||
template = "wgrecord/record_tab_%s" % tab
|
||||
return render_to_response(template + ".html",
|
||||
{'content':content,
|
||||
'charter':ch, 'info':info, 'wg':wg, 'tab':tab,
|
||||
'rev': rev if rev else ch.rev, 'gh': gh,
|
||||
'active_rev': active_rev,
|
||||
'snapshot': rev, 'charter_text_url': charter_text_url,
|
||||
'history': history, 'versions': versions,
|
||||
},
|
||||
context_instance=RequestContext(request));
|
||||
|
||||
def _get_history(wg):
|
||||
results = []
|
||||
for e in wg.groupevent_set.all().select_related('by').order_by('-time', 'id'):
|
||||
info = {}
|
||||
|
||||
charter_history = find_history_active_at(wg.charter, e.time)
|
||||
info['version'] = charter_history.rev if charter_history else wg.charter.rev
|
||||
info['text'] = e.desc
|
||||
info['by'] = e.by.name
|
||||
info['textSnippet'] = truncatewords_html(format_textarea(fill(info['text'], 80)), 25)
|
||||
info['snipped'] = info['textSnippet'][-3:] == "..."
|
||||
results.append({'comment':e, 'info':info, 'date':e.time, 'group': wg, 'is_com':True})
|
||||
|
||||
for e in wg.charter.docevent_set.all().order_by('-time'):
|
||||
info = {}
|
||||
charter_history = find_history_active_at(wg.charter, e.time)
|
||||
info['version'] = charter_history.rev if charter_history else wg.charter.rev
|
||||
info['text'] = e.desc
|
||||
info['by'] = e.by.name
|
||||
info['textSnippet'] = truncatewords_html(format_textarea(fill(info['text'], 80)), 25)
|
||||
info['snipped'] = info['textSnippet'][-3:] == "..."
|
||||
if e.type == "new_revision":
|
||||
if charter_history:
|
||||
charter = get_charter_for_revision(wg.charter, charter_history.rev)
|
||||
group = get_group_for_revision(wg, charter_history.rev)
|
||||
else:
|
||||
charter = get_charter_for_revision(wg.charter, wg.charter.rev)
|
||||
group = get_group_for_revision(wg, wg.charter.rev)
|
||||
|
||||
prev_charter = get_charter_for_revision(wg.charter, prev_revision(charter.rev))
|
||||
prev_group = get_group_for_revision(wg, prev_revision(charter.rev))
|
||||
results.append({'comment':e, 'info':info, 'date':e.time, 'group': group,
|
||||
'charter': charter, 'prev_charter': prev_charter,
|
||||
'prev_group': prev_group,
|
||||
'txt_url': wg.charter.get_txt_url(),
|
||||
'is_rev':True})
|
||||
else:
|
||||
results.append({'comment':e, 'info':info, 'date':e.time, 'group': wg, 'is_com':True})
|
||||
|
||||
# convert plain dates to datetimes (required for sorting)
|
||||
for x in results:
|
||||
if not isinstance(x['date'], datetime):
|
||||
if x['date']:
|
||||
x['date'] = datetime.combine(x['date'], time(0,0,0))
|
||||
else:
|
||||
x['date'] = datetime(1970,1,1)
|
||||
|
||||
results.sort(key=lambda x: x['date'])
|
||||
results.reverse()
|
||||
return results
|
||||
|
||||
def _get_versions(charter, include_replaced=True):
|
||||
ov = []
|
||||
for r in sorted(list(set(charter.history_set.values_list('rev', flat=True)))):
|
||||
if r != "":
|
||||
d = get_charter_for_revision(charter, r)
|
||||
g = get_group_for_revision(charter.chartered_group, r)
|
||||
if d.rev != charter.rev:
|
||||
ov.append({"name": "charter-ietf-%s" % g.acronym, "rev":d.rev, "date":d.time})
|
||||
if charter.rev != "" and (not ov or ov[-1]['rev'] != charter.rev):
|
||||
d = get_charter_for_revision(charter, charter.rev)
|
||||
g = get_group_for_revision(charter.chartered_group, charter.rev)
|
||||
ov.append({"name": "charter-ietf-%s" % g.acronym, "rev": d.rev, "date":d.time})
|
||||
return ov
|
||||
|
||||
def wg_ballot(request, name):
|
||||
try:
|
||||
wg = Group.objects.get(acronym=name)
|
||||
except ObjectDoesNotExist:
|
||||
wglist = GroupHistory.objects.filter(acronym=name)
|
||||
if wglist:
|
||||
return redirect('wg_view_record', name=wglist[0].group.acronym)
|
||||
else:
|
||||
raise Http404
|
||||
|
||||
doc = set_or_create_charter(wg)
|
||||
|
||||
if not doc:
|
||||
raise Http404
|
||||
|
||||
active_ads = list(Person.objects.filter(email__role__name="ad",
|
||||
email__role__group__type="area",
|
||||
email__role__group__state="active").distinct())
|
||||
started_process = doc.latest_event(type="started_iesg_process")
|
||||
latest_positions = []
|
||||
no_record = []
|
||||
for p in active_ads:
|
||||
p_pos = list(GroupBallotPositionDocEvent.objects.filter(doc=wg.charter, ad=p).order_by("-time"))
|
||||
if p_pos != []:
|
||||
latest_positions.append(p_pos[0])
|
||||
else:
|
||||
no_record.append(p)
|
||||
info = {}
|
||||
info['positions'] = latest_positions
|
||||
info['pos_yes'] = filter(lambda x: x.pos_id == "yes", latest_positions)
|
||||
info['pos_no'] = filter(lambda x: x.pos_id == "no", latest_positions)
|
||||
info['pos_block'] = filter(lambda x: x.pos_id == "block", latest_positions)
|
||||
info['pos_abstain'] = filter(lambda x: x.pos_id == "abstain", latest_positions)
|
||||
info['pos_no_record'] = no_record
|
||||
return render_to_response('wgrecord/record_ballot.html', {'info':info, 'wg':wg, 'doc': doc}, context_instance=RequestContext(request))
|
||||
|
|
@ -1,268 +0,0 @@
|
|||
# Copyright The IETF Trust 2011, All Rights Reserved
|
||||
|
||||
import re, os
|
||||
from django import forms
|
||||
from django.shortcuts import render_to_response, redirect
|
||||
from django.db.models import Q
|
||||
from django.template import RequestContext
|
||||
from django.views.decorators.cache import cache_page
|
||||
from django.http import Http404, HttpResponse, HttpResponseBadRequest, HttpResponsePermanentRedirect
|
||||
from redesign.doc.models import Document
|
||||
from redesign.name.models import GroupStateName, CharterDocStateName
|
||||
from redesign.group.models import Group
|
||||
from redesign.person.models import Person, Email
|
||||
from django.conf import settings
|
||||
from django.utils import simplejson
|
||||
|
||||
class SearchForm(forms.Form):
|
||||
nameacronym = forms.CharField(required=False)
|
||||
|
||||
inprocess = forms.BooleanField(required=False,initial=True)
|
||||
active = forms.BooleanField(required=False,initial=False)
|
||||
|
||||
by = forms.ChoiceField(choices=[(x,x) for x in ('acronym','state','ad','area','anyfield', 'eacronym')], required=False, initial='wg', label='Foobar')
|
||||
state = forms.ModelChoiceField(GroupStateName.objects.all(), label="WG state", empty_label="any state", required=False)
|
||||
charter_state = forms.ModelChoiceField(CharterDocStateName.objects.all(), label="Charter state", empty_label="any state", required=False)
|
||||
ad = forms.ChoiceField(choices=(), required=False)
|
||||
area = forms.ModelChoiceField(Group.objects.filter(type="area", state="active").order_by('name'), empty_label="any area", required=False)
|
||||
anyfield= forms.CharField(required=False)
|
||||
eacronym = forms.CharField(required=False)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(SearchForm, self).__init__(*args, **kwargs)
|
||||
responsible = Document.objects.values_list('ad', flat=True).distinct()
|
||||
active_ads = list(Person.objects.filter(email__role__name="ad",
|
||||
email__role__group__type="area",
|
||||
email__role__group__state="active").distinct())
|
||||
inactive_ads = list(Person.objects.filter(pk__in=responsible)
|
||||
.exclude(pk__in=[x.pk for x in active_ads]))
|
||||
extract_last_name = lambda x: x.name_parts()[3]
|
||||
active_ads.sort(key=extract_last_name)
|
||||
inactive_ads.sort(key=extract_last_name)
|
||||
|
||||
self.fields['ad'].choices = c = [('', 'any AD')] + [(ad.pk, ad.name) for ad in active_ads] + [('', '------------------')] + [(ad.pk, ad.name) for ad in inactive_ads]
|
||||
|
||||
def clean_nameacronym(self):
|
||||
value = self.cleaned_data.get('nameacronym','')
|
||||
return value
|
||||
def clean(self):
|
||||
q = self.cleaned_data
|
||||
# Reset query['by'] if needed
|
||||
for k in ('ad', 'area', 'anyfield', 'eacronym'):
|
||||
if (q['by'] == k) and not q[k]:
|
||||
q['by'] = None
|
||||
if (q['by'] == 'state') and not (q['state'] or q['charter_state']):
|
||||
q['by'] = None
|
||||
# Reset other fields
|
||||
for k in ('ad', 'area', 'anyfield', 'eacronym'):
|
||||
if q['by'] != k:
|
||||
self.data[k] = ""
|
||||
q[k] = ""
|
||||
if q['by'] != 'state':
|
||||
self.data['state'] = ""
|
||||
self.data['charter_state'] = ""
|
||||
q['state'] = ""
|
||||
q['charter_state'] = ""
|
||||
return q
|
||||
|
||||
def search_query(query_original, sort_by=None):
|
||||
query = dict(query_original.items())
|
||||
|
||||
# Non-ASCII strings don't match anything; this check
|
||||
# is currently needed to avoid complaints from MySQL.
|
||||
for k in ['nameacronym','anyfield','eacronym']:
|
||||
try:
|
||||
tmp = str(query.get(k, ''))
|
||||
except:
|
||||
query[k] = '*NOSUCH*'
|
||||
|
||||
# Search
|
||||
MAX = 500
|
||||
maxReached = False
|
||||
|
||||
if query["inprocess"]:
|
||||
if query["active"]:
|
||||
results = Group.objects.filter(type="wg")
|
||||
else:
|
||||
results = Group.objects.filter(type="wg").exclude(charter__charter_state__slug="approved")
|
||||
else:
|
||||
if query["active"]:
|
||||
results = Group.objects.filter(type="wg", charter__charter_state__slug="approved")
|
||||
else:
|
||||
raise Http404 # Empty, prevented by js
|
||||
|
||||
prefix = ""
|
||||
q_objs = []
|
||||
# name
|
||||
if query["nameacronym"]:
|
||||
results = results.filter(Q(name__icontains=query["nameacronym"]) | Q(acronym__icontains=query["nameacronym"]))
|
||||
# radio choices
|
||||
by = query["by"]
|
||||
if by == "state":
|
||||
q_objs = []
|
||||
if query['state']:
|
||||
q_objs.append(Q(state=query['state']))
|
||||
if query['charter_state']:
|
||||
q_objs.append(Q(charter__charter_state=query['charter_state']))
|
||||
results = results.filter(*q_objs)
|
||||
elif by == "ad":
|
||||
results = results.filter(ad=query["ad"])
|
||||
elif by == "area":
|
||||
results = results.filter(parent=query["area"])
|
||||
elif by == "anyfield":
|
||||
q_obj = Q()
|
||||
q_obj |= Q(state__name__icontains=query['anyfield'])
|
||||
q_obj |= Q(charter__charter_state__name__icontains=query['anyfield'])
|
||||
q_obj |= Q(ad__name__icontains=query['anyfield'])
|
||||
q_obj |= Q(parent__name__icontains=query['anyfield'])
|
||||
q_obj |= Q(history_set__acronym__icontains=query['anyfield'])
|
||||
results = list(results.filter(q_obj))
|
||||
# Search charter texts
|
||||
m = re.compile(query['anyfield'], re.IGNORECASE)
|
||||
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
|
||||
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()
|
||||
|
||||
results = list(results[:MAX])
|
||||
if len(results) == MAX:
|
||||
maxReached = True
|
||||
|
||||
# sort
|
||||
def sort_key(g):
|
||||
res = []
|
||||
|
||||
if sort_by == "acronym":
|
||||
res.append(g.acronym)
|
||||
elif sort_by == "name":
|
||||
res.append(g.name)
|
||||
elif sort_by == "date":
|
||||
res.append(str(g.time or datetime.date(1990, 1, 1)))
|
||||
elif sort_by == "status":
|
||||
res.append(g.charter.charter_state)
|
||||
|
||||
return res
|
||||
|
||||
results.sort(key=sort_key)
|
||||
|
||||
meta = {}
|
||||
if maxReached:
|
||||
meta['max'] = MAX
|
||||
if query['by']:
|
||||
meta['advanced'] = True
|
||||
return (results,meta)
|
||||
|
||||
def generate_query_string(request, ignore_list):
|
||||
"""Recreates the parameter string from the given request, and
|
||||
returns it as a string.
|
||||
Any parameter names present in ignore_list shall not be put
|
||||
in the result string.
|
||||
"""
|
||||
params = []
|
||||
for i in request.GET:
|
||||
if not i in ignore_list:
|
||||
params.append(i + "=" + request.GET[i])
|
||||
return "?" + "&".join(params)
|
||||
|
||||
def search_results(request):
|
||||
if len(request.REQUEST.items()) == 0:
|
||||
return search_main(request)
|
||||
form = SearchForm(dict(request.REQUEST.items()))
|
||||
if not form.is_valid():
|
||||
return HttpResponseBadRequest("form not valid?", mimetype="text/plain")
|
||||
|
||||
sort_by = None
|
||||
if "sortBy" in request.GET:
|
||||
sort_by = request.GET["sortBy"]
|
||||
|
||||
(results,meta) = search_query(form.cleaned_data, sort_by)
|
||||
|
||||
meta['searching'] = True
|
||||
meta['by'] = form.cleaned_data['by']
|
||||
meta['rqps'] = generate_query_string(request, ['sortBy'])
|
||||
# With a later Django we can do this from the template (incude with tag)
|
||||
# Pass the headers and their sort key names
|
||||
meta['hdrs'] = [{'htitle': 'Acronym', 'htype':'acronym'},
|
||||
{'htitle': 'Name', 'htype':'name'},
|
||||
{'htitle': 'Date', 'htype':'date'},
|
||||
{'htitle': 'Status', 'htype':'status', 'colspan':'2'},
|
||||
]
|
||||
if 'ajax' in request.REQUEST and request.REQUEST['ajax']:
|
||||
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('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))
|
||||
|
||||
|
||||
def search_main(request):
|
||||
form = SearchForm()
|
||||
return render_to_response('wgrecord/search_main.html', {'form':form}, context_instance=RequestContext(request))
|
||||
|
||||
def by_ad(request, name):
|
||||
ad_id = None
|
||||
ad_name = None
|
||||
for p in Person.objects.filter(email__role__name__in=("ad", "ex-ad")):
|
||||
if name == p.name.lower().replace(" ", "."):
|
||||
ad_id = p.id
|
||||
ad_name = p.name
|
||||
break
|
||||
if not ad_id:
|
||||
raise Http404
|
||||
form = SearchForm({'by':'ad','ad':ad_id})
|
||||
if not form.is_valid():
|
||||
raise ValueError("form did not validate")
|
||||
(results,meta) = search_query(form.cleaned_data)
|
||||
meta['searching'] = True
|
||||
meta['by'] = form.cleaned_data['by']
|
||||
meta['rqps'] = generate_query_string(request, ['sortBy'])
|
||||
# With a later Django we can do this from the template (incude with tag)
|
||||
# Pass the headers and their sort key names
|
||||
meta['hdrs'] = [{'htitle': 'Acronym', 'htype':'acronym'},
|
||||
{'htitle': 'Name', 'htype':'name'},
|
||||
{'htitle': 'Date', 'htype':'date'},
|
||||
{'htitle': 'Status', 'htype':'status', 'colspan':'2'},
|
||||
]
|
||||
results.sort(key=lambda g: str(g.time or datetime.date(1990, 1, 1)), reverse=True)
|
||||
return render_to_response('wgrecord/by_ad.html', {'form':form, 'recs':results,'meta':meta, 'ad_name':ad_name}, context_instance=RequestContext(request))
|
||||
|
||||
def in_process(request):
|
||||
results = Group.objects.filter(type="wg",
|
||||
charter__charter_state__in=['infrev', 'intrev', 'extrev', 'iesgrev']).order_by('-time')
|
||||
meta = {}
|
||||
meta['searching'] = True
|
||||
meta['by'] = 'state'
|
||||
meta['rqps'] = generate_query_string(request, ['sortBy'])
|
||||
# With a later Django we can do this from the template (incude with tag)
|
||||
# Pass the headers and their sort key names
|
||||
meta['hdrs'] = [{'htitle': 'Acronym', 'htype':'acronym'},
|
||||
{'htitle': 'Name', 'htype':'name'},
|
||||
{'htitle': 'Date', 'htype':'date'},
|
||||
{'htitle': 'Status', 'htype':'status', 'colspan':'2'},
|
||||
]
|
||||
return render_to_response('wgrecord/in_process.html', {'recs':results,'meta':meta}, context_instance=RequestContext(request))
|
||||
|
||||
def json_emails(list):
|
||||
result = []
|
||||
for p in list:
|
||||
result.append({"id": p.address + "", "name":p.person.name + " <" + p.address + ">"})
|
||||
return simplejson.dumps(result)
|
||||
|
||||
def search_person(request):
|
||||
if request.method == 'GET':
|
||||
emails = Email.objects.filter(person__name__istartswith=request.GET.get('q','')).order_by('person__name')
|
||||
return HttpResponse(json_emails(emails), mimetype='application/json')
|
|
@ -1,93 +0,0 @@
|
|||
# Copyright The IETF Trust 2011, All Rights Reserved
|
||||
import os
|
||||
|
||||
from datetime import datetime
|
||||
from django.http import HttpResponseRedirect, Http404
|
||||
from django import forms
|
||||
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 Group, save_group_in_history
|
||||
from doc.models import Document, DocHistory, DocEvent
|
||||
|
||||
from django.conf import settings
|
||||
from utils import next_revision, set_or_create_charter, save_charter_in_history
|
||||
|
||||
class UploadForm(forms.Form):
|
||||
content = forms.CharField(widget=forms.Textarea, label="Charter text", help_text="Edit the charter text", required=False)
|
||||
txt = forms.FileField(label=".txt format", help_text="Or upload a .txt file", required=False)
|
||||
|
||||
def clean_content(self):
|
||||
return self.cleaned_data["content"].replace("\r", "")
|
||||
|
||||
def save(self, wg, rev):
|
||||
fd = self.cleaned_data['txt']
|
||||
filename = os.path.join(settings.CHARTER_PATH, 'charter-ietf-%s-%s.txt' % (wg.acronym, rev))
|
||||
if fd:
|
||||
# A file was specified. Save it.
|
||||
destination = open(filename, 'wb+')
|
||||
for chunk in fd.chunks():
|
||||
destination.write(chunk)
|
||||
destination.close()
|
||||
else:
|
||||
# No file, save content
|
||||
destination = open(filename, 'wb+')
|
||||
content = self.cleaned_data['content']
|
||||
destination.write(content)
|
||||
destination.close()
|
||||
|
||||
@group_required('Area_Director','Secretariat')
|
||||
def submit(request, name):
|
||||
# Get WG by acronym, redirecting if there's a newer acronym
|
||||
try:
|
||||
wg = Group.objects.get(acronym=name)
|
||||
except ObjectDoesNotExist:
|
||||
wglist = GroupHistory.objects.filter(acronym=name)
|
||||
if wglist:
|
||||
return redirect('charter_submit', name=wglist[0].group.acronym)
|
||||
else:
|
||||
raise Http404
|
||||
# Get charter
|
||||
charter = set_or_create_charter(wg)
|
||||
|
||||
login = request.user.get_profile()
|
||||
|
||||
if request.method == 'POST':
|
||||
form = UploadForm(request.POST, request.FILES)
|
||||
if form.is_valid():
|
||||
save_charter_in_history(charter)
|
||||
# Also save group history so we can search for it
|
||||
save_group_in_history(wg)
|
||||
|
||||
charter.rev = next_revision(charter.rev)
|
||||
|
||||
e = DocEvent()
|
||||
e.type = "new_revision"
|
||||
e.by = login
|
||||
e.doc = charter
|
||||
e.desc = "New version available: <b>charter-ietf-%s-%s.txt</b>" % (wg.acronym, charter.rev)
|
||||
e.save()
|
||||
|
||||
# Save file on disk
|
||||
form.save(wg, charter.rev)
|
||||
|
||||
charter.time = datetime.now()
|
||||
charter.save()
|
||||
|
||||
return HttpResponseRedirect(reverse('wg_view_record', kwargs={'name': wg.acronym}))
|
||||
else:
|
||||
filename = os.path.join(settings.CHARTER_PATH, 'charter-ietf-%s-%s.txt' % (wg.acronym, wg.charter.rev))
|
||||
try:
|
||||
charter_text = open(filename, 'r')
|
||||
init = dict(content = charter_text.read())
|
||||
except IOError:
|
||||
init = {}
|
||||
form = UploadForm(initial = init)
|
||||
return render_to_response('wgrecord/submit.html',
|
||||
{'form': form,
|
||||
'next_rev': next_revision(wg.charter.rev),
|
||||
'wg': wg},
|
||||
context_instance=RequestContext(request))
|
Loading…
Reference in a new issue