Remove wgchairs app, all of its functionality is now superceded by wginfo/ and other recent developments in doc/
- Legacy-Id: 6198
This commit is contained in:
parent
19fc7c14bc
commit
a871d6e19e
|
@ -9,7 +9,7 @@ trap 'echo "$program($LINENO): Command failed with error code $? ($0 $*)"; exit
|
|||
if [ "$*" ]; then apps="$@"; graph="${1%.*}"; else apps=$(ls */models.py | sed 's!/models.py!!'); graph="models"; fi
|
||||
|
||||
newapps="doc group meeting message person name"
|
||||
legacyapps="announcements idindex idrfc idtracker iesg ietfauth ietfworkflows ipr liaisons mailinglists proceedings redirects submit wgchairs wgcharter wginfo"
|
||||
legacyapps="announcements idindex idrfc idtracker iesg ietfauth ietfworkflows ipr liaisons mailinglists proceedings redirects submit wgcharter wginfo"
|
||||
|
||||
proxy="$(grep ^class */proxy.py | tr '()' ' ' | awk '{printf $2 ","}')"
|
||||
names="$(grep ^class name/models.py | tr '()' ' ' | awk '{printf $2 ","}')"
|
||||
|
|
|
@ -194,11 +194,6 @@ class InternetDraft(Document):
|
|||
def authors(self):
|
||||
return IDAuthor.objects.filter(document=self)
|
||||
|
||||
@property
|
||||
def protowriteup_set(self):
|
||||
from ietf.wgchairs.models import ProtoWriteUpProxy
|
||||
return ProtoWriteUpProxy.objects.filter(doc=self, type="changed_protocol_writeup")
|
||||
|
||||
# methods from InternetDraft
|
||||
def displayname(self):
|
||||
return self.name
|
||||
|
|
|
@ -94,6 +94,19 @@ def proxied_role_emails(emails):
|
|||
proxy_role_email(e)
|
||||
return emails
|
||||
|
||||
class WGDelegateProxy(Role):
|
||||
#person = models.ForeignKey(PersonOrOrgInfo) # same name
|
||||
#wg = models.ForeignKey(IETFWG)
|
||||
@property
|
||||
def wg(self):
|
||||
return self.group
|
||||
|
||||
def __unicode__(self):
|
||||
return u"%s" % self.person
|
||||
|
||||
class Meta:
|
||||
proxy = True
|
||||
|
||||
class IETFWG(Group):
|
||||
objects = TranslatingManager(dict(group_acronym="id",
|
||||
group_acronym__acronym="acronym",
|
||||
|
@ -211,8 +224,7 @@ class IETFWG(Group):
|
|||
return d
|
||||
@property
|
||||
def wgdelegate_set(self):
|
||||
from ietf.wgchairs.models import WGDelegate
|
||||
return WGDelegate.objects.filter(group=self, name="delegate")
|
||||
return WGDelegateProxy.objects.filter(group=self, name="delegate")
|
||||
|
||||
class Meta:
|
||||
proxy = True
|
||||
|
|
|
@ -175,7 +175,6 @@ INSTALLED_APPS = (
|
|||
'ietf.wginfo',
|
||||
'ietf.submit',
|
||||
'ietf.ietfworkflows',
|
||||
'ietf.wgchairs',
|
||||
'ietf.wgcharter',
|
||||
'ietf.sync',
|
||||
'ietf.community',
|
||||
|
|
|
@ -1,55 +0,0 @@
|
|||
{% extends "wginfo/wg_base.html" %}
|
||||
{% load ietf_filters wgchairs_tags %}
|
||||
|
||||
{% block title %}Change shepherd write-up for {{ doc }}{% endblock %}
|
||||
|
||||
{% block wg_content %}
|
||||
|
||||
<p>
|
||||
<a href="{% url manage_shepherds wg.group_acronym.acronym %}">Return to shepherd list</a>
|
||||
</p>
|
||||
|
||||
<h1>Updating write-up for {{ doc }}</h1>
|
||||
|
||||
<p>
|
||||
Before you modify the shepherd write-up <strong>please revise the 'Doc Shepherd Follow-up Underway' annotation tag and set or reset it if appropriate</strong>.
|
||||
</p>
|
||||
<p>
|
||||
Remember that you must provide a comment if you change the annotation tag state.
|
||||
</p>
|
||||
|
||||
<form action="" method="POST">
|
||||
<table style="width: 100%;"><tr style="vertical-align: top;"><td style="width: 50%;">
|
||||
<table class="ietf-table" style="width: 100%;">
|
||||
<tr><th>Doc Shepherd Follow-up Underway</th></tr>
|
||||
{% if form.message %}
|
||||
<tr><td class="message message-{{ form.message.type }}">
|
||||
{{ form.message.value }}
|
||||
</td></tr>
|
||||
{% endif %}
|
||||
|
||||
<tr><td>
|
||||
<input type="hidden" value="{{ form.get_writeup }}" name="writeup" />
|
||||
<input type="hidden" value="confirm" name="confirm" />
|
||||
<input type="checkbox" name="followup" id="followup_id" value="1"{% if followup %} checked="checked"{% endif %} />
|
||||
<label for="followup_id">Doc Shepherd Follow-up Underway</label>
|
||||
</td></tr><tr><td>
|
||||
{{ form.comment }}
|
||||
</td></tr>
|
||||
</table>
|
||||
<p>
|
||||
<strong>Change write-up and ...</strong><br />
|
||||
<input type="submit" name="modify_tag" value="Modify 'Doc Shepherd Follow-up Underway'" />
|
||||
<input type="submit" name="change_writeup" value="Leave 'Doc Shepherd Follow-up Underway' untouched" /><br />
|
||||
<a href="">Cancel, I don't want to do any change!</a>
|
||||
</p>
|
||||
|
||||
</td><td style="width: 50%;">
|
||||
<table class="ietf-table" style="width: 100%;">
|
||||
<tr><th>New shepherd write-up</th></tr>
|
||||
<tr style="vertical-align: top;"><td>{{ form.get_writeup|linebreaksbr }}</td></tr>
|
||||
</table>
|
||||
|
||||
</td></tr></table>
|
||||
</form>
|
||||
{% endblock %}
|
|
@ -1 +0,0 @@
|
|||
{{ state.name }}
|
|
@ -1,41 +0,0 @@
|
|||
{% extends "wginfo/wg_base.html" %}
|
||||
{% load ietf_filters %}
|
||||
|
||||
{% block title %}Change shepherd for {{ doc }}{% endblock %}
|
||||
|
||||
{% block wg_content %}
|
||||
|
||||
<p>
|
||||
<a href="{% url manage_shepherds wg.group_acronym.acronym %}">Return to shepherd list</a>
|
||||
<a href="{{ doc.get_absolute_url }}">Return to {{ doc }}</a>
|
||||
</p>
|
||||
|
||||
<h1>Change shepherd for {{ doc }}</h1>
|
||||
|
||||
<table style="width: 100%;"><tr style="vertical-align: top;"><td style="width: 50%;">
|
||||
<form action="" method="POST">
|
||||
<table class="ietf-table" style="width: 100%;">
|
||||
<tr><th>Actual shepherd</th></tr>
|
||||
<tr><td>{% if doc.shepherd %}{{ doc.shepherd }}{% else %}No shepherd assigned{% endif %}</td></tr>
|
||||
</table>
|
||||
<input type="hidden" name="update_shepherd" value="1" />
|
||||
<input type="submit" name="remove_shepherd" value="Unassign shepherd" />
|
||||
<input type="submit" name="setme" value="Set me as shepherd of this document" />
|
||||
</form>
|
||||
</td><td style="width: 50%;">
|
||||
<form action="" method="POST">
|
||||
<table class="ietf-table" style="width: 100%;">
|
||||
<tr><th>Change shepherd</th></tr>
|
||||
{% if form.message %}
|
||||
<tr><td class="message message-{{ form.message.type }}">
|
||||
{{ form.message.value }}
|
||||
</td></tr>
|
||||
{% endif %}
|
||||
|
||||
<tr><td>{{ form.as_p }}</td></tr>
|
||||
</table>
|
||||
<input type="submit" name="change_shepherd" value="Change shepherd" />
|
||||
{% if form.can_cancel %}<a href="">No! I don't want to continue</a>{% endif %}
|
||||
</form>
|
||||
</td></tr></table>
|
||||
{% endblock %}
|
|
@ -1,67 +0,0 @@
|
|||
{% extends "wginfo/wg_base.html" %}
|
||||
{% load ietf_filters wgchairs_tags %}
|
||||
|
||||
{% block title %} {% if can_edit %} Change {% else %} View {% endif %} shepherd write-up for {{ doc }}{% endblock %}
|
||||
|
||||
{% block wg_content %}
|
||||
|
||||
<p>
|
||||
<a href="{% url manage_shepherds wg.group_acronym.acronym %}">Return to shepherd list</a>
|
||||
</p>
|
||||
|
||||
<h1> {% if can_edit %} Change {% else %} View {% endif %} shepherd write-up for {{ doc }}</h1>
|
||||
|
||||
<table class="ietf-table" style="width: 100%;">
|
||||
<tr><th>Draft state</th><th>Actual shepherd write-up</th><th>Last updated</th></tr>
|
||||
<tr style="vertical-align: top;"><td>{% show_state doc %}</td><td>{{ writeup.writeup|linebreaksbr }}</td><td>{% if writeup %}{{ writeup.date }} by {{ writeup.person }}{% endif %}</td></tr>
|
||||
</table>
|
||||
|
||||
<p>
|
||||
Please, <strong>note</strong> that the <strong>'Doc Shepherd Follow-up Underway'</strong> annotation tag is {% if not followup %}<strong>NOT</strong>{% endif %} set for {{ doc }}.
|
||||
</p>
|
||||
|
||||
{% if can_edit %}
|
||||
<table style="width: 100%;"><tr style="vertical-align: top;"><td style="width: 75%;">
|
||||
<form action="" method="POST">
|
||||
<table class="ietf-table" style="width: 100%;">
|
||||
<tr><th>Edit shepherd write-up</th></tr>
|
||||
{% if form.message %}
|
||||
<tr><td class="message message-{{ form.message.type }}">
|
||||
{{ form.message.value }}
|
||||
</td></tr>
|
||||
{% endif %}
|
||||
|
||||
<tr><td>
|
||||
<textarea name="writeup" style="border: 1px solid #cccccc; width: 100%; height: 15em;">{{ form.get_writeup }}</textarea></td></tr>
|
||||
</table>
|
||||
<input type="submit" name="change_writeup" value="Change write-up" />
|
||||
</form>
|
||||
|
||||
</td><td style="width: 25%;">
|
||||
|
||||
<form action="" method="POST" enctype="multipart/form-data">
|
||||
<table class="ietf-table" style="width: 100%;">
|
||||
<tr><th>Upload a new shepherd write-up</th></tr>
|
||||
<tr><td>
|
||||
<p>Replace the current write-up with the contents of a plain ascii file:</p>
|
||||
<input type="file" name="uploaded_writeup" /></td></tr>
|
||||
</table>
|
||||
<input type="submit" name="upload_writeup" value="Upload write-up" />
|
||||
</form>
|
||||
</td></tr></table>
|
||||
{% else %}
|
||||
{% if authorized_user %}
|
||||
<table class="ietf-table" style="width: 100%;">
|
||||
<tr><th>Edit shepherd write-up</th></tr>
|
||||
<tr><td>
|
||||
<p>
|
||||
You can not edit or upload the shepherd write-up for {{ doc }} because the draft is not on "WG Consensus: Waiting for Write-Up" state.
|
||||
</p>
|
||||
<p>
|
||||
Please contact with the {{ wg }} Working Group chair.
|
||||
</p>
|
||||
</td></tr>
|
||||
</table>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
|
@ -1,60 +0,0 @@
|
|||
{% extends "wginfo/wg_base.html" %}
|
||||
|
||||
|
||||
{% block wg_titledetail %}Delegates{% endblock %}
|
||||
|
||||
{% block wg_content %}
|
||||
<div class="wg-chair-management">
|
||||
|
||||
<h2>Manage delegates</h2>
|
||||
<p>
|
||||
Sometimes, a WG has one (or more) WG Secretaries, in addition to the WG Chairs.
|
||||
This page lets the WG Chairs delegate the authority to do updates to the WG state of WG documents in the datatracker.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
You may at most delegate the datatracker update rights to {{ max_delegates }} persons at any given time.
|
||||
</p>
|
||||
|
||||
<table style="width: 100%;">
|
||||
<tr style="vertical-align: top;"><td>
|
||||
{% if delegates %}
|
||||
<form action="" method="POST">
|
||||
<table class="ietf-table" style="width: 100%">
|
||||
<tr><th>Remove</th><th style="Width: 100%">Delegate name</th></tr>
|
||||
{% for delegate in delegates %}
|
||||
<tr class="{% cycle "oddrow" "evenrow" %}"><td><input type="checkbox" name="delete" value="{{ delegate.pk }}" /></td><td>{{ delegate.person }}</td></tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
<input type="submit" value="Remove delegate(s)" name="remove" />
|
||||
</form>
|
||||
{% else %}
|
||||
No delegates
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
<table class="ietf-table" style="width: 100%;">
|
||||
<tr><th>Add new delegate</th></tr>
|
||||
{% if add_form.message %}
|
||||
<tr><td class="message message-{{ add_form.message.type }}">
|
||||
{{ add_form.message.value }}
|
||||
</td></tr>
|
||||
{% endif %}
|
||||
<tr><td>
|
||||
{% if can_add %}
|
||||
<form action="" method="POST">
|
||||
{{ add_form.as_p }}
|
||||
<p>
|
||||
<input type="submit" value="{% if add_form.submit_msg %}{{ add_form.submit_msg }}{% else %}Add delegate{% endif %}" name="add" />
|
||||
{% if add_form.can_cancel %}<a href="">No! I don't want to continue</a>{% endif %}
|
||||
</p>
|
||||
</form>
|
||||
{% else %}
|
||||
You can only assign {{ max_delegates }} delegates. Please remove delegates to add a new one.
|
||||
{% endif %}
|
||||
</td></tr>
|
||||
</table>
|
||||
</td></tr>
|
||||
</table>
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -1,165 +0,0 @@
|
|||
{% extends "wginfo/wg_base.html" %}
|
||||
|
||||
{% block wg_titledetail %}Manage Workflow{% endblock %}
|
||||
|
||||
{% block pagehead %}
|
||||
{{ block.super }}
|
||||
<script type="text/javascript" src="/js/lib/jquery-1.4.2.min.js"></script>
|
||||
<script type="text/javascript" src="/js/yui/yui-20100305.js"></script>
|
||||
<script type="text/javascript" src="/js/base.js"></script>
|
||||
{% endblock pagehead %}
|
||||
|
||||
{% block wg_content %}
|
||||
<div class="wg-workflow-management">
|
||||
<h2>Edit workflow</h2>
|
||||
<div id="mytabs" class="yui-navset">
|
||||
<ul class="yui-nav">
|
||||
<li class="selected"><a href="#info"><em>Info</em></a></li>
|
||||
<li><a href="#states"><em>Select states</em></a></li>
|
||||
<li><a href="#transitions"><em>Edit transitions</em></a></li>
|
||||
<li><a href="#tags"><em>Select Annotation Tags</em></a></li>
|
||||
</ul>
|
||||
|
||||
<div class="yui-content">
|
||||
<div id="info">
|
||||
<table style="width: 100%;"><tr style="vertical-align: top;"><td>
|
||||
<table class="ietf-table" style="width: 100%">
|
||||
<tr>
|
||||
<th>States used in {{ wg }} Working Group</th>
|
||||
</tr>
|
||||
{% for state in states %}
|
||||
<tr class="{% cycle "oddrow" "evenrow" %}">
|
||||
<td>{{ state.name }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table><br />
|
||||
<table class="ietf-table" style="width: 100%;">
|
||||
<tr>
|
||||
<th>Annotation tags used in {{ wg }} Working Group</th>
|
||||
</tr>
|
||||
{% for tag in tags %}
|
||||
<tr class="{% cycle "oddrow" "evenrow" %}">
|
||||
<td>{{ tag.name }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
</td><td>
|
||||
<table class="ietf-table" style="width: 100%;">
|
||||
<tr>
|
||||
<th>Transition name</th><th>Initial states</th><th>Destination state</th>
|
||||
</tr>
|
||||
{% for transition in workflow.transitions.all %}
|
||||
<tr class="{% cycle "oddrow" "evenrow" %}">
|
||||
<td>
|
||||
{{ transition.name }}
|
||||
</td>
|
||||
<td>
|
||||
{% for state in transition.states.all %}
|
||||
{{state.name }}{% if not forloop.last %}<br />{% endif %}
|
||||
{% endfor %}
|
||||
</td>
|
||||
<td>
|
||||
{{ transition.destination.name }}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% if not workflow.transitions.all.count %}
|
||||
<tr class="oddrow"><td colspan="3">There are no transitions defined so any state change is allowed</td></tr>
|
||||
{% endif %}
|
||||
</table>
|
||||
</td></tr></table>
|
||||
</div>
|
||||
|
||||
<div id="states">
|
||||
<p>
|
||||
Please note that the states you can not uncheck are needed in all IETF WGs.
|
||||
</p>
|
||||
<p>
|
||||
You can see the default Working Group I-D State Diagram in <a href="http://tools.ietf.org/html/rfc6174#section-4.1">Section 4.1 of RFC6174</a>
|
||||
</p>
|
||||
<form action="#info" method="POST">
|
||||
<table class="ietf-table">
|
||||
<tr>
|
||||
<th>Used in {{ wg }}</th><th>Available states</th><th>Definition</th>
|
||||
</tr>
|
||||
{% for state in default_states %}
|
||||
<tr class="{% cycle "oddrow" "evenrow" %}" style="vertical-align: top;">
|
||||
<td><input type="checkbox" id="id_states_{{ state.pk }}" name="states" value="{{ state.pk }}" {% if state.used %}checked="checked" {% endif %}{% if state.freeze %} disabled="disabled"{% endif %}/></td>
|
||||
<td><label for="id_states_{{ state.pk }}">{{ state.name }}</label></td>
|
||||
<td>
|
||||
<div class="statedefinition" style="height: 1em; overflow: hidden;">
|
||||
<pre style="margin-top: 0px;"><a class="showDefinition" href="#">[+]</a><a class="hideDefinition" style="display: none;" href="#">[-]</a> {{ state.statedescription_set.all.0.definition|safe }}</pre>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
<input type="submit" name="update_states" value="Update states" />
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div id="transitions">
|
||||
<p>
|
||||
You can see the default Working Group I-D State Diagram in <a href="http://tools.ietf.org/html/rfc6174#section-4.1">Section 4.1 of RFC6174</a>
|
||||
</p>
|
||||
<form action="#transitions" method="POST">
|
||||
<table class="ietf-table">
|
||||
<tr>
|
||||
<th>Delete</th><th>Transition name</th><th>Initial states</th><th>Destination state</th>
|
||||
</tr>
|
||||
{{ formset.as_table }}
|
||||
</table>
|
||||
<input type="submit" name="update_transitions" value="Update transitions" />
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div id="tags">
|
||||
<form action="#info" method="POST">
|
||||
<table class="ietf-table">
|
||||
<tr>
|
||||
<th>Used in {{ wg }}</th><th>Available annotation tags</th>
|
||||
</tr>
|
||||
{% for tag in default_tags %}
|
||||
<tr class="{% cycle "oddrow" "evenrow" %}">
|
||||
<td><input type="checkbox" id="id_tags_{{ tag.pk }}" name="tags" value="{{ tag.pk }}" {% if tag.used %}checked="checked" {% endif %}/></td>
|
||||
<td><label for="id_tags_{{ tag.pk }}">{{ tag.name }}</label></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
<input type="submit" name="update_tags" value="Update tags" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
//<![CDATA[
|
||||
var tabView = new YAHOO.widget.TabView('mytabs');
|
||||
var url = location.href.split('#');
|
||||
if (url[1]) {
|
||||
url[1] = "#"+url[1];
|
||||
var tabs = tabView.get('tabs');
|
||||
for (var i = 0; i < tabs.length; i++) {
|
||||
if (url[1].indexOf(tabs[i].get('href')) == 0) {
|
||||
tabView.set('activeIndex', i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
jQuery('.showDefinition').click(function() {
|
||||
jQuery(this).parent().parent().css('height', 'auto');
|
||||
jQuery(this).hide();
|
||||
jQuery(this).next().show();
|
||||
return false;
|
||||
});
|
||||
jQuery('.hideDefinition').click(function() {
|
||||
jQuery(this).parent().parent().css('height', '1em');
|
||||
jQuery(this).hide();
|
||||
jQuery(this).prev().show();
|
||||
return false;
|
||||
});
|
||||
//]]>
|
||||
</script>
|
||||
|
||||
{% endblock %}
|
|
@ -1,28 +0,0 @@
|
|||
{% if shepherd %}
|
||||
<p>
|
||||
The shepherd you are trying to designate does not have a personal user-id and password to log-on to the Datatracker.
|
||||
</p>
|
||||
<p>
|
||||
An email will be sent to the following addresses to inform that
|
||||
the person you have designated to be one of your document shepherds
|
||||
currently does not have login credentials for the Datatracker
|
||||
and should contact the Secretariat to obtain their own user-id and
|
||||
password for the Datatracker.
|
||||
</p>
|
||||
{% else %}
|
||||
<p>
|
||||
The delegate you are trying to designate does not have a personal user-id and password to log-on to the Datatracker.
|
||||
</p>
|
||||
<p>
|
||||
An email will be sent to the following addresses to inform that
|
||||
the person you have designated to be one of your delegates
|
||||
currently does not have login credentials for the Datatracker
|
||||
and should contact the Secretariat to obtain their own user-id and
|
||||
password for the Datatracker.
|
||||
</p>
|
||||
{% endif %}
|
||||
<ul>
|
||||
{% for email in email_list %}
|
||||
<li>{{ email }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
|
@ -1,10 +0,0 @@
|
|||
{% autoescape off %}{{ chair }} as a WG Chair of {{ wg }} wants to add you as a {{ wg }} {% if shepherd %}shepherd of document {{ shepherd }}{% else %}WG Delegate{% endif %}.
|
||||
|
||||
You don't have an user/password to log into the datatracker so you must contact
|
||||
the Secretariat at iesg-secretary@ietf.org in order to get your credentials.
|
||||
|
||||
When you get your credentials, please inform {{ chair }} at
|
||||
{{ chair.email.1 }} so he/she can finish the designate process.
|
||||
|
||||
Thank you.
|
||||
{% endautoescape %}
|
|
@ -1,15 +0,0 @@
|
|||
{% autoescape off %}{{ chair }} as a WG Chair of {{ wg }} wants to add a person with email
|
||||
{{ delegate_email }} as a {% if shepherd %}shepherd of document {{ shepherd }}{% else %}WG Delegate{% endif %}.
|
||||
|
||||
This person don't have an user/password to log into the datatracker so
|
||||
an email has been seent to {{ delegate_email }} in order to he/she contacs the
|
||||
Secretariat to request his/her credentials.
|
||||
|
||||
{% if delegate_persons %}
|
||||
Please, note that the following persons with {{ delegate_email }} email address
|
||||
already exists in the system but they can not log in.
|
||||
{% for person in delegate_persons %}
|
||||
{{ person.pk }} - {{ person }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endautoescape %}
|
|
@ -1,12 +0,0 @@
|
|||
{% autoescape off %}{{ chair }} as a WG Chair of {{ wg }} wants to add a person with email
|
||||
{{ delegate_email }} as a {% if shepherd %}shepherd of document {{ shepherd }}{% else %}WG Delegate{% endif %}.
|
||||
|
||||
This person don't have an user/password to log into the datatracker so
|
||||
an email has been seent to {{ delegate_email }} in order to he/she contacs the
|
||||
Secretariat to request his/her credentials.
|
||||
|
||||
When he/she gets her credentials then he/she will send an email to
|
||||
{{ chair }} at {{ chair.email.1 }}.
|
||||
|
||||
{{ chair }} could then assign this person as {% if shepherd %}shepherd of document {{ shepherd }}{% else %}WG Delegate{% endif %}.
|
||||
{% endautoescape%}
|
|
@ -1,17 +0,0 @@
|
|||
{% load wgchairs_tags %}
|
||||
|
||||
<tr class="{{ forloop.counter|divisibleby:2|yesno:"oddrow,evenrow" }}">
|
||||
<td class="title">
|
||||
<a href="{% url doc_view doc.filename %}">{{ doc.title }}</a>
|
||||
</td>
|
||||
<td class="shepherd">
|
||||
<a href="{% url doc_edit_shepherd doc %}">Change shepherd</a>
|
||||
</td>
|
||||
<td class="writeup">
|
||||
{% writeup doc %}
|
||||
<a href="{% url doc_edit_shepherd_writeup doc %}" style="display: block;" href="">[Edit]</a>
|
||||
</td>
|
||||
<td class="writeup_date">
|
||||
{% writeupdate doc %}
|
||||
</td>
|
||||
</tr>
|
|
@ -1,122 +0,0 @@
|
|||
{% extends "wginfo/wg_base.html" %}
|
||||
{% comment %}
|
||||
Copyright (C) 2010 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.
|
||||
{% endcomment %}
|
||||
{% block wg_titledetail %}Documents{% endblock %}
|
||||
|
||||
{% block pagehead %}
|
||||
{{ block.super }}
|
||||
<script type="text/javascript" src="/js/lib/jquery-1.4.2.min.js"></script>
|
||||
<script type="text/javascript" src="/js/yui/yui-20100305.js"></script>
|
||||
<script type="text/javascript" src="/js/base.js"></script>
|
||||
{% endblock pagehead %}
|
||||
|
||||
{% block wg_content %}
|
||||
|
||||
<h2>Documents by its shepherd</h2>
|
||||
<div id="mytabs" class="yui-navset">
|
||||
<ul class="yui-nav">
|
||||
<li class="selected"><a href="#noshepherd"><em>Without shepherd</em></a></li>
|
||||
<li><a href="#mydocs"><em>Shepherded by me</em></a></li>
|
||||
<li><a href="#othershepherds"><em>Shepherded by others</em></a></li>
|
||||
</ul>
|
||||
|
||||
<div class="yui-content">
|
||||
<div id="noshepherd">
|
||||
<table class="ietf-table ietf-doctable" style="margin-top:16px; width: 100%;">
|
||||
<tr>
|
||||
<th class="title">Document</th>
|
||||
<th class="shepherd">Change shepherd</th>
|
||||
<th class="writeup">Shepherd write-up</th>
|
||||
<th class="writeup_date">Shepherd write-up last update</th>
|
||||
</tr>
|
||||
|
||||
{% for doc in no_shepherd %}
|
||||
{% include "wgchairs/shepherd_document_row.html" %}
|
||||
{% endfor %}
|
||||
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div id="mydocs">
|
||||
<table class="ietf-table ietf-doctable" style="margin-top:16px; width: 100%;">
|
||||
<tr>
|
||||
<th class="title">Document</th>
|
||||
<th class="status">Status</th>
|
||||
<th class="writeup">Shepherd write-up</th>
|
||||
<th class="writeup_date">Shepherd write-up last update</th>
|
||||
</tr>
|
||||
|
||||
{% for doc in my_documents %}
|
||||
{% include "wgchairs/shepherd_document_row.html" %}
|
||||
{% endfor %}
|
||||
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div id="othershepherds">
|
||||
{% regroup other_shepherds by shepherd as regrouped %}
|
||||
{% for documents in regrouped %}
|
||||
<h3 style="margin-bottom: 0px;">{{ documents.grouper }}</h3>
|
||||
<table class="ietf-table ietf-doctable" style="width: 100%;">
|
||||
<tr>
|
||||
<th class="title">Document</th>
|
||||
<th class="status">Status</th>
|
||||
<th class="writeup">Shepherd write-up</th>
|
||||
<th class="writeup_date">Shepherd write-up last update</th>
|
||||
</tr>
|
||||
{% for doc in documents.list %}
|
||||
{% include "wgchairs/shepherd_document_row.html" %}
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
//<![CDATA[
|
||||
var tabView = new YAHOO.widget.TabView('mytabs');
|
||||
var url = location.href.split('#');
|
||||
if (url[1]) {
|
||||
url[1] = "#"+url[1];
|
||||
var tabs = tabView.get('tabs');
|
||||
for (var i = 0; i < tabs.length; i++) {
|
||||
if (url[1].indexOf(tabs[i].get('href')) == 0) {
|
||||
tabView.set('activeIndex', i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
//]]>
|
||||
</script>
|
||||
{% endblock wg_content %}
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
{% if can_manage_workflow %}
|
||||
{% ifequal selected "manage_workflow" %}
|
||||
<span class="selected">Manage workflow</span>
|
||||
{% else %}
|
||||
<a href="{% url manage_workflow wg.group_acronym.acronym %}">Manage workflow</a>
|
||||
{% endifequal %} |
|
||||
{% endif %}
|
||||
|
||||
{% if can_manage_delegates %}
|
||||
{% ifequal selected "manage_delegates" %}
|
||||
<span class="selected">Manage delegations</span>
|
||||
{% else %}
|
||||
<a href="{% url manage_delegates wg.group_acronym.acronym %}">Manage delegations</a>
|
||||
{% endifequal %} |
|
||||
{% endif %}
|
||||
|
||||
{% if can_manage_shepherds %}
|
||||
{% ifequal selected "manage_shepherds" %}
|
||||
<span class="selected">Manage shepherds</span>
|
||||
{% else %}
|
||||
<a href="{% url manage_shepherds wg.group_acronym.acronym %}">Manage shepherds</a>
|
||||
{% endifequal %} |
|
||||
{% endif %}
|
|
@ -1,83 +0,0 @@
|
|||
{% extends "base.html" %}
|
||||
{% comment %}
|
||||
Copyright (C) 2010 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.
|
||||
{% endcomment %}
|
||||
{% load ietf_filters wgchairs_tags %}
|
||||
{% block title %}{{wg.group_acronym.name}} ({{wg.group_acronym.acronym}}) - {% block wg_titledetail %}{% endblock %}{% endblock %}
|
||||
|
||||
{% block morecss %}
|
||||
.ietf-navset {
|
||||
background:#214197 url(/images/yui/sprite.png) repeat-x left -1400px;
|
||||
color:white;
|
||||
border:1px solid black;
|
||||
padding:4px;
|
||||
}
|
||||
.ietf-navset .selected { font-weight:bold; padding: 0 3px; }
|
||||
.ietf-navset a, .ietf-navset a:visited { color: white; padding:0 3px; }
|
||||
|
||||
.ietf-wg-details { float:right; padding: 4px;margin-top:16px; margin-left: 16px; }
|
||||
.ietf-wg-details tr { vertical-align: top; }
|
||||
.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;}
|
||||
.ietf-box th {
|
||||
font-weight: bold;
|
||||
padding-top: 1em;
|
||||
text-align: left;
|
||||
}
|
||||
.ietf-box tr:first-child th {
|
||||
padding-top: 0;
|
||||
}
|
||||
{% endblock morecss %}
|
||||
|
||||
{% block content %}
|
||||
<div {% if concluded %}class="ietf-concluded-bg"{% endif %} {% if proposed %}class="ietf-proposed-bg"{% endif %}>
|
||||
<h1>{{wg.group_acronym.name}} ({{wg.group_acronym.acronym}}){% if concluded %}<br/><span class="ietf-concluded-warning">(concluded WG)</span>{% endif %}{% if proposed %}<br/><span class="ietf-proposed-warning">(proposed WG)</span>{% endif %}</h1>
|
||||
|
||||
<div class="ietf-navset">
|
||||
{% ifequal selected "documents" %}<span class="selected">Documents</span>{% else %}<a href="{% url ietf.wginfo.views.group_documents acronym=wg.group_acronym.acronym %}">Documents</a>{% endifequal %} |
|
||||
{% ifequal selected "charter" %}<span class="selected">Charter</span>{% else %}<a href="{% url ietf.wginfo.views.group_charter acronym=wg.group_acronym.acronym %}">Charter</a>{% endifequal %} |
|
||||
{% wgchairs_admin_options wg %}
|
||||
<a {% if selected == "history" %}class="selected"{% else %}href="{% url ietf.wginfo.views.history acronym=wg.group_acronym.acronym %}"{% endif %}>History</a> |
|
||||
{% if wg.clean_email_archive|startswith:"http:" or wg.clean_email_archive|startswith:"https:" or wg.clean_email_archive|startswith:"ftp:" %}
|
||||
<a href="{{ wg.clean_email_archive }}">List Archive »</a> |
|
||||
{% endif %}
|
||||
<a href="http://tools.ietf.org/wg/{{ wg.group_acronym.acronym }}/">Tools WG Page »</a>
|
||||
</div>
|
||||
|
||||
{% block wg_content %}
|
||||
{% endblock wg_content %}
|
||||
|
||||
</div>
|
||||
{% endblock content %}
|
1
ietf/wgchairs/.gitignore
vendored
1
ietf/wgchairs/.gitignore
vendored
|
@ -1 +0,0 @@
|
|||
/*.pyc
|
|
@ -1,18 +0,0 @@
|
|||
# coding: latin-1
|
||||
|
||||
from types import ModuleType
|
||||
import urls, models, views, forms, accounts
|
||||
|
||||
# These people will be sent a stack trace if there's an uncaught exception in
|
||||
# code any of the modules imported above:
|
||||
DEBUG_EMAILS = [
|
||||
('Emilio A. Sánchez', 'esanchez@yaco.es'),
|
||||
]
|
||||
|
||||
for k in locals().keys():
|
||||
m = locals()[k]
|
||||
if isinstance(m, ModuleType):
|
||||
if hasattr(m, "DEBUG_EMAILS"):
|
||||
DEBUG_EMAILS += list(getattr(m, "DEBUG_EMAILS"))
|
||||
setattr(m, "DEBUG_EMAILS", DEBUG_EMAILS)
|
||||
|
|
@ -1,108 +0,0 @@
|
|||
from django.conf import settings
|
||||
from ietf.group.models import Role
|
||||
|
||||
def is_secretariat(user):
|
||||
if not user or not user.is_authenticated():
|
||||
return False
|
||||
return bool(user.groups.filter(name='Secretariat'))
|
||||
|
||||
|
||||
def is_area_director_for_group(person, group):
|
||||
return bool(group.area.area.areadirector_set.filter(person=person).count())
|
||||
|
||||
def is_area_director_for_groupREDESIGN(person, group):
|
||||
return bool(Role.objects.filter(group=group.parent, person=person, name__in=("ad", "pre-ad")))
|
||||
|
||||
|
||||
def is_group_chair(person, group):
|
||||
if group.chairs().filter(person=person):
|
||||
return True
|
||||
return False
|
||||
|
||||
def is_group_chairREDESIGN(person, group):
|
||||
return bool(Role.objects.filter(group=group, person=person, name="chair"))
|
||||
|
||||
|
||||
def is_group_delegate(person, group):
|
||||
return bool(group.wgdelegate_set.filter(person=person).count())
|
||||
|
||||
def is_group_delegateREDESIGN(person, group):
|
||||
return bool(Role.objects.filter(group=group, person=person, name="delegate"))
|
||||
|
||||
|
||||
def get_person_for_user(user):
|
||||
try:
|
||||
return user.get_profile().person()
|
||||
except:
|
||||
return None
|
||||
|
||||
|
||||
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
|
||||
from ietf.liaisons.accounts import is_secretariat, get_person_for_user
|
||||
is_area_director_for_group = is_area_director_for_groupREDESIGN
|
||||
is_group_chair = is_group_chairREDESIGN
|
||||
is_group_delegate = is_group_delegateREDESIGN
|
||||
|
||||
|
||||
def can_do_wg_workflow_in_group(user, group):
|
||||
person = get_person_for_user(user)
|
||||
if not person:
|
||||
return False
|
||||
return (is_secretariat(user) or is_group_chair(person, group))
|
||||
|
||||
|
||||
def can_do_wg_workflow_in_document(user, document):
|
||||
person = get_person_for_user(user)
|
||||
if not person or not document.group:
|
||||
return False
|
||||
return (is_secretariat(user) or can_do_wg_workflow_in_group(document.group.ietfwg))
|
||||
|
||||
|
||||
def can_manage_workflow_in_group(user, group):
|
||||
person = get_person_for_user(user)
|
||||
if not person:
|
||||
return False
|
||||
return (is_secretariat(user) or is_group_chair(person, group))
|
||||
|
||||
|
||||
def can_manage_delegates_in_group(user, group):
|
||||
person = get_person_for_user(user)
|
||||
if not person:
|
||||
return False
|
||||
return (is_secretariat(user) or is_group_chair(person, group))
|
||||
|
||||
|
||||
def can_manage_shepherds_in_group(user, group):
|
||||
person = get_person_for_user(user)
|
||||
if not person:
|
||||
return False
|
||||
return (is_secretariat(user) or is_group_chair(person, group))
|
||||
|
||||
|
||||
def can_manage_shepherd_of_a_document(user, document):
|
||||
person = get_person_for_user(user)
|
||||
if not person or not document.group:
|
||||
return False
|
||||
return can_manage_shepherds_in_group(user, document.group.ietfwg)
|
||||
|
||||
|
||||
def can_manage_writeup_of_a_document_no_state(user, document):
|
||||
person = get_person_for_user(user)
|
||||
if not person or not document.group:
|
||||
return False
|
||||
group = document.group.ietfwg
|
||||
return (is_secretariat(user) or
|
||||
is_group_chair(person, group) or
|
||||
is_area_director_for_group(person, group) or
|
||||
is_group_delegate(person, group))
|
||||
|
||||
|
||||
def can_manage_writeup_of_a_document(user, document):
|
||||
person = get_person_for_user(user)
|
||||
if not person or not document.group:
|
||||
return False
|
||||
return (can_manage_writeup_of_a_document_no_state(user, document) or
|
||||
person == document.shepherd)
|
||||
|
||||
|
||||
|
|
@ -1,478 +0,0 @@
|
|||
import datetime
|
||||
|
||||
from django import forms
|
||||
from django.conf import settings
|
||||
from django.db.models import Q
|
||||
from django.forms.models import BaseModelFormSet
|
||||
from django.template.loader import render_to_string
|
||||
from django.utils.safestring import mark_safe
|
||||
|
||||
from ietf.wgchairs.models import WGDelegate, ProtoWriteUp
|
||||
from ietf.wgchairs.accounts import get_person_for_user
|
||||
from ietf.ietfworkflows.constants import REQUIRED_STATES
|
||||
from ietf.ietfworkflows.utils import (get_default_workflow_for_wg, get_workflow_for_wg,
|
||||
update_tags, FOLLOWUP_TAG, get_state_by_name)
|
||||
from ietf.ietfworkflows.models import AnnotationTag, State
|
||||
from ietf.idtracker.models import PersonOrOrgInfo
|
||||
from ietf.utils.mail import send_mail_text
|
||||
|
||||
from workflows.models import Transition
|
||||
|
||||
from ietf.doc.models import WriteupDocEvent
|
||||
from ietf.person.models import Person, Email
|
||||
from ietf.group.models import Group, Role, RoleName
|
||||
from ietf.group.utils import save_group_in_history
|
||||
from ietf.name.models import DocTagName
|
||||
|
||||
|
||||
class RelatedWGForm(forms.Form):
|
||||
|
||||
can_cancel = False
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.wg = kwargs.pop('wg', None)
|
||||
self.user = kwargs.pop('user', None)
|
||||
self.message = {}
|
||||
super(RelatedWGForm, self).__init__(*args, **kwargs)
|
||||
|
||||
def get_message(self):
|
||||
return self.message
|
||||
|
||||
def set_message(self, msg_type, msg_value):
|
||||
self.message = {'type': msg_type,
|
||||
'value': msg_value,
|
||||
}
|
||||
|
||||
|
||||
class TagForm(RelatedWGForm):
|
||||
|
||||
tags = forms.ModelMultipleChoiceField(AnnotationTag.objects.filter(workflow__name='Default WG Workflow'),
|
||||
widget=forms.CheckboxSelectMultiple, required=False)
|
||||
|
||||
def save(self):
|
||||
workflow = get_workflow_for_wg(self.wg)
|
||||
workflow.selected_tags.clear()
|
||||
for tag in self.cleaned_data['tags']:
|
||||
workflow.selected_tags.add(tag)
|
||||
return workflow
|
||||
|
||||
|
||||
class StateForm(RelatedWGForm):
|
||||
|
||||
states = forms.ModelMultipleChoiceField(State.objects.filter(workflow__name='Default WG Workflow'),
|
||||
widget=forms.CheckboxSelectMultiple, required=False)
|
||||
|
||||
def update_transitions(self, workflow):
|
||||
for transition in workflow.transitions.all():
|
||||
if not workflow.selected_states.filter(pk=transition.destination.pk).count():
|
||||
transition.delete()
|
||||
continue
|
||||
for state in transition.states.all():
|
||||
if not workflow.selected_states.filter(pk=state.pk).count():
|
||||
transition.states.remove(state)
|
||||
if not transition.states.count():
|
||||
transition.delete()
|
||||
continue
|
||||
|
||||
def save(self):
|
||||
workflow = get_workflow_for_wg(self.wg)
|
||||
workflow.selected_states.clear()
|
||||
for state in self.cleaned_data['states']:
|
||||
workflow.selected_states.add(state)
|
||||
for name in REQUIRED_STATES:
|
||||
rstate = get_state_by_name(name)
|
||||
if rstate:
|
||||
workflow.selected_states.add(rstate)
|
||||
self.update_transitions(workflow)
|
||||
return workflow
|
||||
|
||||
|
||||
class DeleteTransitionForm(RelatedWGForm):
|
||||
|
||||
transitions = forms.ModelMultipleChoiceField(Transition.objects.all(),
|
||||
widget=forms.CheckboxSelectMultiple)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(DeleteTransitionForm, self).__init__(*args, **kwargs)
|
||||
workflow = get_workflow_for_wg(self.wg)
|
||||
self.fields['transitions'].queryset = self.fields['transitions'].queryset.filter(workflow=workflow)
|
||||
|
||||
def save(self):
|
||||
for transition in self.cleaned_data['transitions']:
|
||||
transition.delete()
|
||||
|
||||
|
||||
class TransitionForm(forms.ModelForm):
|
||||
|
||||
states = forms.ModelMultipleChoiceField(State.objects.filter(workflow__name='Default WG Workflow'))
|
||||
|
||||
class Meta:
|
||||
model = Transition
|
||||
fields = ('name', 'states', 'destination', )
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.wg = kwargs.pop('wg', None)
|
||||
self.user = kwargs.pop('user', None)
|
||||
super(TransitionForm, self).__init__(*args, **kwargs)
|
||||
workflow = get_workflow_for_wg(self.wg)
|
||||
self.fields['states'].queryset = workflow.selected_states.all()
|
||||
self.fields['destination'].queryset = workflow.selected_states.all()
|
||||
self.fields['destination'].required = True
|
||||
if self.instance.pk:
|
||||
self.fields['states'].initial = [i.pk for i in self.instance.states.all()]
|
||||
self.instance.workflow = workflow
|
||||
|
||||
def as_row(self):
|
||||
return self._html_output(u'<td>%(errors)s%(field)s%(help_text)s</td>', u'<td colspan="2">%s</td>', '</td>', u'<br />%s', False)
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
instance = super(TransitionForm, self).save(*args, **kwargs)
|
||||
for state in self.cleaned_data['states']:
|
||||
state.transitions.add(instance)
|
||||
|
||||
|
||||
class TransitionFormSet(BaseModelFormSet):
|
||||
|
||||
form = TransitionForm
|
||||
can_delete = True
|
||||
extra = 2
|
||||
max_num = 0
|
||||
can_order = False
|
||||
model = Transition
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.wg = kwargs.pop('wg', None)
|
||||
self.user = kwargs.pop('user', None)
|
||||
super(TransitionFormSet, self).__init__(*args, **kwargs)
|
||||
|
||||
def _construct_form(self, i, **kwargs):
|
||||
kwargs = kwargs or {}
|
||||
kwargs.update({'wg': self.wg, 'user': self.user})
|
||||
return super(TransitionFormSet, self)._construct_form(i, **kwargs)
|
||||
|
||||
def as_table(self):
|
||||
html = u''
|
||||
csscl = 'oddrow'
|
||||
for form in self.forms:
|
||||
html += u'<tr class="%s">' % csscl
|
||||
html += form.as_row()
|
||||
html += u'</tr>'
|
||||
if csscl == 'oddrow':
|
||||
csscl = 'evenrow'
|
||||
else:
|
||||
csscl = 'oddrow'
|
||||
return mark_safe(u'\n'.join([unicode(self.management_form), html]))
|
||||
|
||||
|
||||
def workflow_form_factory(request, wg, user):
|
||||
|
||||
if request.POST.get('update_transitions', None):
|
||||
return TransitionFormSet(wg=wg, user=user, data=request.POST)
|
||||
elif request.POST.get('update_states', None):
|
||||
return StateForm(wg=wg, user=user, data=request.POST)
|
||||
return TagForm(wg=wg, user=user, data=request.POST)
|
||||
|
||||
|
||||
class RemoveDelegateForm(RelatedWGForm):
|
||||
|
||||
delete = forms.MultipleChoiceField()
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(RemoveDelegateForm, self).__init__(*args, **kwargs)
|
||||
self.fields['delete'].choices = [(i.pk, i.pk) for i in self.wg.wgdelegate_set.all()]
|
||||
|
||||
def save(self):
|
||||
delegates = self.cleaned_data.get('delete')
|
||||
save_group_in_history(Group.objects.get(pk=self.wg.pk))
|
||||
WGDelegate.objects.filter(pk__in=delegates).delete()
|
||||
self.set_message('success', 'Delegates removed')
|
||||
|
||||
def assign_shepherd(user, internetdraft, shepherd):
|
||||
if internetdraft.shepherd == shepherd:
|
||||
return
|
||||
|
||||
from ietf.doc.models import save_document_in_history, DocEvent, Document
|
||||
|
||||
# saving the proxy object is a bit of a mess, so convert it to a
|
||||
# proper document
|
||||
doc = Document.objects.get(name=internetdraft.name)
|
||||
|
||||
save_document_in_history(doc)
|
||||
|
||||
doc.time = datetime.datetime.now()
|
||||
doc.shepherd = shepherd
|
||||
doc.save()
|
||||
|
||||
e = DocEvent(type="changed_document")
|
||||
e.time = doc.time
|
||||
e.doc = doc
|
||||
e.by = user.get_profile()
|
||||
if not shepherd:
|
||||
e.desc = u"Unassigned shepherd"
|
||||
else:
|
||||
e.desc = u"Changed shepherd to %s" % shepherd.plain_name()
|
||||
e.save()
|
||||
|
||||
# update proxy too
|
||||
internetdraft.shepherd = shepherd
|
||||
|
||||
class AddDelegateForm(RelatedWGForm):
|
||||
|
||||
email = forms.EmailField()
|
||||
form_type = forms.CharField(widget=forms.HiddenInput, initial='single')
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.shepherd = kwargs.pop('shepherd', False)
|
||||
super(AddDelegateForm, self).__init__(*args, **kwargs)
|
||||
self.next_form = self
|
||||
|
||||
def get_next_form(self):
|
||||
return self.next_form
|
||||
|
||||
def get_person(self, email):
|
||||
persons = PersonOrOrgInfo.objects.filter(emailaddress__address=email).filter(
|
||||
Q(iesglogin__isnull=False)|
|
||||
Q(legacywgpassword__isnull=False)|
|
||||
Q(legacyliaisonuser__isnull=False)).distinct()
|
||||
if not persons:
|
||||
raise PersonOrOrgInfo.DoesNotExist
|
||||
if len(persons) > 1:
|
||||
raise PersonOrOrgInfo.MultipleObjectsReturned
|
||||
return persons[0]
|
||||
|
||||
def save(self):
|
||||
email = self.cleaned_data.get('email')
|
||||
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
|
||||
try:
|
||||
person = Person.objects.filter(email__address=email).exclude(user=None).distinct().get()
|
||||
except Person.DoesNotExist:
|
||||
self.next_form = NotExistDelegateForm(wg=self.wg, user=self.user, email=email, shepherd=self.shepherd)
|
||||
self.next_form.set_message('doesnotexist', 'There is no user with this email allowed to login to the system')
|
||||
return
|
||||
except Person.MultipleObjectsReturned:
|
||||
self.next_form = MultipleDelegateForm(wg=self.wg, user=self.user, email=email, shepherd=self.shepherd)
|
||||
self.next_form.set_message('multiple', 'There are multiple users with this email in the system')
|
||||
return
|
||||
else:
|
||||
try:
|
||||
person = self.get_person(email)
|
||||
except PersonOrOrgInfo.DoesNotExist:
|
||||
self.next_form = NotExistDelegateForm(wg=self.wg, user=self.user, email=email, shepherd=self.shepherd)
|
||||
self.next_form.set_message('doesnotexist', 'There is no user with this email allowed to login to the system')
|
||||
return
|
||||
except PersonOrOrgInfo.MultipleObjectsReturned:
|
||||
self.next_form = MultipleDelegateForm(wg=self.wg, user=self.user, email=email, shepherd=self.shepherd)
|
||||
self.next_form.set_message('multiple', 'There are multiple users with this email in the system')
|
||||
return
|
||||
if self.shepherd:
|
||||
self.assign_shepherd(person)
|
||||
else:
|
||||
self.create_delegate(person)
|
||||
|
||||
def assign_shepherd(self, person):
|
||||
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
|
||||
assign_shepherd(self.user, self.shepherd, person)
|
||||
else:
|
||||
self.shepherd.shepherd = person
|
||||
self.shepherd.save()
|
||||
self.next_form = AddDelegateForm(wg=self.wg, user=self.user, shepherd=self.shepherd)
|
||||
self.next_form.set_message('success', 'Shepherd assigned successfully')
|
||||
|
||||
def create_delegate(self, person):
|
||||
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
|
||||
created = False
|
||||
e = Email.objects.get(address=self.cleaned_data.get('email'))
|
||||
if not Role.objects.filter(name="delegate", group=self.wg, person=person, email=e):
|
||||
created = True
|
||||
save_group_in_history(Group.objects.get(pk=self.wg.pk))
|
||||
delegate, _ = Role.objects.get_or_create(
|
||||
name=RoleName.objects.get(slug="delegate"), group=self.wg, person=e.person, email=e)
|
||||
else:
|
||||
(delegate, created) = WGDelegate.objects.get_or_create(wg=self.wg,
|
||||
person=person)
|
||||
if not created:
|
||||
self.set_message('error', 'The email belongs to a person who is already a delegate')
|
||||
else:
|
||||
self.next_form = AddDelegateForm(wg=self.wg, user=self.user)
|
||||
self.next_form.set_message('success', 'A new delegate has been added')
|
||||
|
||||
|
||||
class MultipleDelegateForm(AddDelegateForm):
|
||||
|
||||
email = forms.EmailField(widget=forms.HiddenInput)
|
||||
form_type = forms.CharField(widget=forms.HiddenInput, initial='multiple')
|
||||
persons = forms.ChoiceField(widget=forms.RadioSelect, help_text='Please select one person from the list')
|
||||
submit_msg = 'Designate as delegate'
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.email = kwargs.pop('email', None)
|
||||
super(MultipleDelegateForm, self).__init__(*args, **kwargs)
|
||||
if not self.email:
|
||||
self.email = self.data.get('email', None)
|
||||
self.fields['email'].initial = self.email
|
||||
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
|
||||
self.fields['persons'].choices = [(i.pk, unicode(i)) for i in Person.objects.filter(email__address=self.email).exclude(user=None).distinct().order_by('name')]
|
||||
else:
|
||||
self.fields['persons'].choices = [(i.pk, unicode(i)) for i in PersonOrOrgInfo.objects.filter(emailaddress__address=self.email).filter(
|
||||
Q(iesglogin__isnull=False)|
|
||||
Q(legacywgpassword__isnull=False)|
|
||||
Q(legacyliaisonuser__isnull=False)).distinct().order_by('first_name')]
|
||||
|
||||
def save(self):
|
||||
person_id = self.cleaned_data.get('persons')
|
||||
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
|
||||
person = Person.objects.get(pk=person_id)
|
||||
else:
|
||||
person = PersonOrOrgInfo.objects.get(pk=person_id)
|
||||
if self.shepherd:
|
||||
self.assign_shepherd(person)
|
||||
else:
|
||||
self.create_delegate(person)
|
||||
|
||||
|
||||
class NotExistDelegateForm(MultipleDelegateForm):
|
||||
|
||||
email = forms.EmailField(widget=forms.HiddenInput)
|
||||
form_type = forms.CharField(widget=forms.HiddenInput, initial='notexist')
|
||||
can_cancel = True
|
||||
submit_msg = 'Send email to these addresses'
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(NotExistDelegateForm, self).__init__(*args, **kwargs)
|
||||
self.email_list = []
|
||||
del(self.fields['persons'])
|
||||
|
||||
def get_email_list(self):
|
||||
if self.email_list:
|
||||
return self.email_list
|
||||
email_list = [self.email]
|
||||
email_list.append('IETF Secretariat <iesg-secretary@ietf.org>')
|
||||
email_list += ['%s <%s>' % i.person.email() for i in self.wg.wgchair_set.all() if i.person.email()]
|
||||
self.email_list = email_list
|
||||
return email_list
|
||||
|
||||
def as_p(self):
|
||||
email_list = self.get_email_list()
|
||||
info = render_to_string('wgchairs/notexistdelegate.html', {'email_list': email_list, 'shepherd': self.shepherd})
|
||||
return info + super(NotExistDelegateForm, self).as_p()
|
||||
|
||||
def send_email(self, to_email, template):
|
||||
if self.shepherd:
|
||||
subject = 'WG shepherd needs system credentials'
|
||||
else:
|
||||
subject = 'WG Delegate needs system credentials'
|
||||
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
|
||||
persons = Person.objects.filter(email__address=self.email).distinct()
|
||||
else:
|
||||
persons = PersonOrOrgInfo.objects.filter(emailaddress__address=self.email).distinct()
|
||||
body = render_to_string(template,
|
||||
{'chair': get_person_for_user(self.user),
|
||||
'delegate_email': self.email,
|
||||
'shepherd': self.shepherd,
|
||||
'delegate_persons': persons,
|
||||
'wg': self.wg,
|
||||
})
|
||||
|
||||
send_mail_text(self.request, to_email, settings.DEFAULT_FROM_EMAIL, subject, body)
|
||||
|
||||
def save(self):
|
||||
self.next_form = AddDelegateForm(wg=self.wg, user=self.user)
|
||||
if settings.DEBUG:
|
||||
self.next_form.set_message('warning', 'Email was not sent cause tool is in DEBUG mode')
|
||||
else:
|
||||
# this is ugly...
|
||||
email_list = self.get_email_list()
|
||||
delegate = email_list[0]
|
||||
secretariat = email_list[1]
|
||||
wgchairs = email_list[2:]
|
||||
self.send_email(delegate, 'wgchairs/notexistsdelegate_delegate_email.txt')
|
||||
self.send_email(secretariat, 'wgchairs/notexistsdelegate_secretariat_email.txt')
|
||||
self.send_email(wgchairs, 'wgchairs/notexistsdelegate_wgchairs_email.txt')
|
||||
self.next_form.set_message('success', 'Email sent successfully')
|
||||
|
||||
|
||||
def add_form_factory(request, wg, user, shepherd=False):
|
||||
if request.method != 'POST' or request.POST.get('update_shepehrd'):
|
||||
return AddDelegateForm(wg=wg, user=user, shepherd=shepherd)
|
||||
|
||||
if request.POST.get('form_type', None) == 'multiple':
|
||||
f = MultipleDelegateForm(wg=wg, user=user, data=request.POST.copy(), shepherd=shepherd)
|
||||
elif request.POST.get('form_type', None) == 'notexist':
|
||||
f = NotExistDelegateForm(wg=wg, user=user, data=request.POST.copy(), shepherd=shepherd)
|
||||
elif request.POST.get('form_type', None) == 'single':
|
||||
f = AddDelegateForm(wg=wg, user=user, data=request.POST.copy(), shepherd=shepherd)
|
||||
else:
|
||||
f = AddDelegateForm(wg=wg, user=user, shepherd=shepherd)
|
||||
|
||||
f.request = request
|
||||
return f
|
||||
|
||||
class WriteUpEditForm(RelatedWGForm):
|
||||
|
||||
writeup = forms.CharField(widget=forms.Textarea, required=False)
|
||||
followup = forms.BooleanField(required=False)
|
||||
comment = forms.CharField(widget=forms.Textarea, required=False)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.doc = kwargs.pop('doc', None)
|
||||
self.doc_writeup = self.doc.protowriteup_set.all()
|
||||
if self.doc_writeup.count():
|
||||
self.doc_writeup = self.doc_writeup[0]
|
||||
else:
|
||||
self.doc_writeup = None
|
||||
super(WriteUpEditForm, self).__init__(*args, **kwargs)
|
||||
self.person = get_person_for_user(self.user)
|
||||
|
||||
def get_writeup(self):
|
||||
return self.data.get('writeup', self.doc_writeup and self.doc_writeup.writeup or '')
|
||||
|
||||
def save(self):
|
||||
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
|
||||
e = WriteupDocEvent(type="changed_protocol_writeup")
|
||||
e.doc = self.doc
|
||||
e.by = self.person
|
||||
e.desc = e.get_type_display()
|
||||
e.text = self.cleaned_data['writeup']
|
||||
e.save()
|
||||
from ietf.wgchairs.models import ProtoWriteUpProxy
|
||||
self.doc_writeup = ProtoWriteUpProxy.objects.get(pk=e.pk)
|
||||
else:
|
||||
if not self.doc_writeup:
|
||||
self.doc_writeup = ProtoWriteUp.objects.create(
|
||||
person=self.person,
|
||||
draft=self.doc,
|
||||
writeup=self.cleaned_data['writeup'])
|
||||
else:
|
||||
self.doc_writeup.writeup = self.cleaned_data['writeup']
|
||||
self.doc_writeup.save()
|
||||
|
||||
if self.data.get('modify_tag', False):
|
||||
followup = self.cleaned_data.get('followup', False)
|
||||
comment = self.cleaned_data.get('comment', False)
|
||||
try:
|
||||
shepherd = self.doc.shepherd
|
||||
except PersonOrOrgInfo.DoesNotExist:
|
||||
shepherd = None
|
||||
if shepherd:
|
||||
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
|
||||
extra_notify = [shepherd.formatted_email()]
|
||||
else:
|
||||
extra_notify = ['%s <%s>' % shepherd.email()]
|
||||
else:
|
||||
extra_notify = []
|
||||
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
|
||||
tags = DocTagName.objects.filter(slug="sheph-u")
|
||||
else:
|
||||
tags = [FOLLOWUP_TAG]
|
||||
if followup:
|
||||
update_tags(self.request, self.doc, comment, self.person, set_tags=tags, extra_notify=extra_notify)
|
||||
else:
|
||||
update_tags(self.request, self.doc, comment, self.person, reset_tags=tags, extra_notify=extra_notify)
|
||||
return self.doc_writeup
|
||||
|
||||
def is_valid(self):
|
||||
if self.data.get('confirm', False) and self.data.get('modify_tag', False):
|
||||
self.fields['comment'].required = True
|
||||
else:
|
||||
self.fields['comment'].required = False
|
||||
return super(WriteUpEditForm, self).is_valid()
|
1
ietf/wgchairs/migrations/.gitignore
vendored
1
ietf/wgchairs/migrations/.gitignore
vendored
|
@ -1 +0,0 @@
|
|||
/*.pyc
|
|
@ -1,110 +0,0 @@
|
|||
|
||||
from south.db import db
|
||||
from django.db import models
|
||||
from ietf.wgchairs.models import *
|
||||
|
||||
class Migration:
|
||||
|
||||
def forwards(self, orm):
|
||||
|
||||
# Adding model 'WGDelegate'
|
||||
db.create_table('wgchairs_wgdelegate', (
|
||||
('id', orm['wgchairs.WGDelegate:id']),
|
||||
('person', orm['wgchairs.WGDelegate:person']),
|
||||
('wg', orm['wgchairs.WGDelegate:wg']),
|
||||
))
|
||||
db.send_create_signal('wgchairs', ['WGDelegate'])
|
||||
|
||||
|
||||
|
||||
def backwards(self, orm):
|
||||
|
||||
# Deleting model 'WGDelegate'
|
||||
db.delete_table('wgchairs_wgdelegate')
|
||||
|
||||
|
||||
|
||||
models = {
|
||||
'idtracker.acronym': {
|
||||
'Meta': {'db_table': "'acronym'"},
|
||||
'acronym': ('django.db.models.fields.CharField', [], {'max_length': '12'}),
|
||||
'acronym_id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'name_key': ('django.db.models.fields.CharField', [], {'max_length': '50'})
|
||||
},
|
||||
'idtracker.area': {
|
||||
'Meta': {'db_table': "'areas'"},
|
||||
'area_acronym': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['idtracker.Acronym']", 'unique': 'True', 'primary_key': 'True'}),
|
||||
'comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'concluded_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'extra_email_addresses': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'last_modified_date': ('django.db.models.fields.DateField', [], {'auto_now': 'True', 'blank': 'True'}),
|
||||
'start_date': ('django.db.models.fields.DateField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'status': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.AreaStatus']"})
|
||||
},
|
||||
'idtracker.areadirector': {
|
||||
'Meta': {'db_table': "'area_directors'"},
|
||||
'area': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.Area']", 'null': 'True', 'db_column': "'area_acronym_id'"}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.PersonOrOrgInfo']", 'db_column': "'person_or_org_tag'"})
|
||||
},
|
||||
'idtracker.areastatus': {
|
||||
'Meta': {'db_table': "'area_status'"},
|
||||
'status': ('django.db.models.fields.CharField', [], {'max_length': '25', 'db_column': "'status_value'"}),
|
||||
'status_id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
|
||||
},
|
||||
'idtracker.ietfwg': {
|
||||
'Meta': {'db_table': "'groups_ietf'"},
|
||||
'area_director': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.AreaDirector']", 'null': 'True'}),
|
||||
'comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'concluded_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'dormant_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'email_address': ('django.db.models.fields.CharField', [], {'max_length': '60', 'blank': 'True'}),
|
||||
'email_archive': ('django.db.models.fields.CharField', [], {'max_length': '95', 'blank': 'True'}),
|
||||
'email_keyword': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
|
||||
'email_subscribe': ('django.db.models.fields.CharField', [], {'max_length': '120', 'blank': 'True'}),
|
||||
'group_acronym': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['idtracker.Acronym']", 'unique': 'True', 'primary_key': 'True'}),
|
||||
'group_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.WGType']"}),
|
||||
'last_modified_date': ('django.db.models.fields.DateField', [], {}),
|
||||
'meeting_scheduled': ('django.db.models.fields.CharField', [], {'max_length': '3', 'blank': 'True'}),
|
||||
'meeting_scheduled_old': ('django.db.models.fields.CharField', [], {'max_length': '3', 'blank': 'True'}),
|
||||
'proposed_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'start_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'status': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.WGStatus']"})
|
||||
},
|
||||
'idtracker.personororginfo': {
|
||||
'Meta': {'db_table': "'person_or_org_info'"},
|
||||
'address_type': ('django.db.models.fields.CharField', [], {'max_length': '4', 'null': 'True', 'blank': 'True'}),
|
||||
'created_by': ('django.db.models.fields.CharField', [], {'max_length': '8', 'null': 'True', 'blank': 'True'}),
|
||||
'date_created': ('django.db.models.fields.DateField', [], {'auto_now_add': 'True', 'null': 'True', 'blank': 'True'}),
|
||||
'date_modified': ('django.db.models.fields.DateField', [], {'auto_now': 'True', 'null': 'True', 'blank': 'True'}),
|
||||
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '20', 'blank': 'True'}),
|
||||
'first_name_key': ('django.db.models.fields.CharField', [], {'max_length': '20', 'blank': 'True'}),
|
||||
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
|
||||
'last_name_key': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
|
||||
'middle_initial': ('django.db.models.fields.CharField', [], {'max_length': '4', 'null': 'True', 'blank': 'True'}),
|
||||
'middle_initial_key': ('django.db.models.fields.CharField', [], {'max_length': '4', 'null': 'True', 'blank': 'True'}),
|
||||
'modified_by': ('django.db.models.fields.CharField', [], {'max_length': '8', 'null': 'True', 'blank': 'True'}),
|
||||
'name_prefix': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}),
|
||||
'name_suffix': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}),
|
||||
'person_or_org_tag': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'record_type': ('django.db.models.fields.CharField', [], {'max_length': '8', 'null': 'True', 'blank': 'True'})
|
||||
},
|
||||
'idtracker.wgstatus': {
|
||||
'Meta': {'db_table': "'g_status'"},
|
||||
'status': ('django.db.models.fields.CharField', [], {'max_length': '25', 'db_column': "'status_value'"}),
|
||||
'status_id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
|
||||
},
|
||||
'idtracker.wgtype': {
|
||||
'Meta': {'db_table': "'g_type'"},
|
||||
'group_type_id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'type': ('django.db.models.fields.CharField', [], {'max_length': '25', 'db_column': "'group_type'"})
|
||||
},
|
||||
'wgchairs.wgdelegate': {
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.PersonOrOrgInfo']"}),
|
||||
'wg': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.IETFWG']"})
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['wgchairs']
|
|
@ -1,163 +0,0 @@
|
|||
|
||||
from south.db import db
|
||||
from django.db import models
|
||||
from ietf.wgchairs.models import *
|
||||
|
||||
class Migration:
|
||||
|
||||
def forwards(self, orm):
|
||||
|
||||
# Adding model 'ProtoWriteUp'
|
||||
db.create_table('wgchairs_protowriteup', (
|
||||
('id', orm['wgchairs.protowriteup:id']),
|
||||
('person', orm['wgchairs.protowriteup:person']),
|
||||
('draft', orm['wgchairs.protowriteup:draft']),
|
||||
('date', orm['wgchairs.protowriteup:date']),
|
||||
('writeup', orm['wgchairs.protowriteup:writeup']),
|
||||
))
|
||||
db.send_create_signal('wgchairs', ['ProtoWriteUp'])
|
||||
|
||||
|
||||
|
||||
def backwards(self, orm):
|
||||
|
||||
# Deleting model 'ProtoWriteUp'
|
||||
db.delete_table('wgchairs_protowriteup')
|
||||
|
||||
|
||||
|
||||
models = {
|
||||
'idtracker.acronym': {
|
||||
'Meta': {'db_table': "'acronym'"},
|
||||
'acronym': ('django.db.models.fields.CharField', [], {'max_length': '12'}),
|
||||
'acronym_id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'name_key': ('django.db.models.fields.CharField', [], {'max_length': '50'})
|
||||
},
|
||||
'idtracker.area': {
|
||||
'Meta': {'db_table': "'areas'"},
|
||||
'area_acronym': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['idtracker.Acronym']", 'unique': 'True', 'primary_key': 'True'}),
|
||||
'comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'concluded_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'extra_email_addresses': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'last_modified_date': ('django.db.models.fields.DateField', [], {'auto_now': 'True', 'blank': 'True'}),
|
||||
'start_date': ('django.db.models.fields.DateField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'status': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.AreaStatus']"})
|
||||
},
|
||||
'idtracker.areadirector': {
|
||||
'Meta': {'db_table': "'area_directors'"},
|
||||
'area': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.Area']", 'null': 'True', 'db_column': "'area_acronym_id'"}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.PersonOrOrgInfo']", 'db_column': "'person_or_org_tag'"})
|
||||
},
|
||||
'idtracker.areastatus': {
|
||||
'Meta': {'db_table': "'area_status'"},
|
||||
'status': ('django.db.models.fields.CharField', [], {'max_length': '25', 'db_column': "'status_value'"}),
|
||||
'status_id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
|
||||
},
|
||||
'idtracker.idintendedstatus': {
|
||||
'Meta': {'db_table': "'id_intended_status'"},
|
||||
'intended_status': ('django.db.models.fields.CharField', [], {'max_length': '25', 'db_column': "'status_value'"}),
|
||||
'intended_status_id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
|
||||
},
|
||||
'idtracker.idstatus': {
|
||||
'Meta': {'db_table': "'id_status'"},
|
||||
'status': ('django.db.models.fields.CharField', [], {'max_length': '25', 'db_column': "'status_value'"}),
|
||||
'status_id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
|
||||
},
|
||||
'idtracker.ietfwg': {
|
||||
'Meta': {'db_table': "'groups_ietf'"},
|
||||
'area_director': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.AreaDirector']", 'null': 'True'}),
|
||||
'comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'concluded_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'dormant_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'email_address': ('django.db.models.fields.CharField', [], {'max_length': '60', 'blank': 'True'}),
|
||||
'email_archive': ('django.db.models.fields.CharField', [], {'max_length': '95', 'blank': 'True'}),
|
||||
'email_keyword': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
|
||||
'email_subscribe': ('django.db.models.fields.CharField', [], {'max_length': '120', 'blank': 'True'}),
|
||||
'group_acronym': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['idtracker.Acronym']", 'unique': 'True', 'primary_key': 'True'}),
|
||||
'group_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.WGType']"}),
|
||||
'last_modified_date': ('django.db.models.fields.DateField', [], {}),
|
||||
'meeting_scheduled': ('django.db.models.fields.CharField', [], {'max_length': '3', 'blank': 'True'}),
|
||||
'meeting_scheduled_old': ('django.db.models.fields.CharField', [], {'max_length': '3', 'blank': 'True'}),
|
||||
'proposed_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'start_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'status': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.WGStatus']"})
|
||||
},
|
||||
'idtracker.internetdraft': {
|
||||
'Meta': {'db_table': "'internet_drafts'"},
|
||||
'abstract': ('django.db.models.fields.TextField', [], {}),
|
||||
'b_approve_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'b_discussion_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'b_sent_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'comments': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'dunn_sent_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'expiration_date': ('django.db.models.fields.DateField', [], {'null': 'True'}),
|
||||
'expired_tombstone': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
|
||||
'extension_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'file_type': ('django.db.models.fields.CharField', [], {'max_length': '20'}),
|
||||
'filename': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),
|
||||
'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.Acronym']", 'db_column': "'group_acronym_id'"}),
|
||||
'id_document_key': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'id_document_tag': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'intended_status': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.IDIntendedStatus']"}),
|
||||
'last_modified_date': ('django.db.models.fields.DateField', [], {}),
|
||||
'lc_changes': ('django.db.models.fields.CharField', [], {'max_length': '3', 'null': 'True'}),
|
||||
'lc_expiration_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'lc_sent_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'local_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
|
||||
'replaced_by': ('django.db.models.fields.related.ForeignKey', ["orm['idtracker.InternetDraft']"], {'related_name': "'replaces_set'", 'null': 'True', 'db_column': "'replaced_by'", 'blank': 'True'}),
|
||||
'review_by_rfc_editor': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
|
||||
'revision': ('django.db.models.fields.CharField', [], {'max_length': '2'}),
|
||||
'revision_date': ('django.db.models.fields.DateField', [], {}),
|
||||
'rfc_number': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
|
||||
'shepherd': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.PersonOrOrgInfo']", 'null': 'True', 'blank': 'True'}),
|
||||
'start_date': ('django.db.models.fields.DateField', [], {}),
|
||||
'status': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.IDStatus']"}),
|
||||
'title': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_column': "'id_document_name'"}),
|
||||
'txt_page_count': ('django.db.models.fields.IntegerField', [], {}),
|
||||
'wgreturn_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'})
|
||||
},
|
||||
'idtracker.personororginfo': {
|
||||
'Meta': {'db_table': "'person_or_org_info'"},
|
||||
'address_type': ('django.db.models.fields.CharField', [], {'max_length': '4', 'null': 'True', 'blank': 'True'}),
|
||||
'created_by': ('django.db.models.fields.CharField', [], {'max_length': '8', 'null': 'True', 'blank': 'True'}),
|
||||
'date_created': ('django.db.models.fields.DateField', [], {'auto_now_add': 'True', 'null': 'True', 'blank': 'True'}),
|
||||
'date_modified': ('django.db.models.fields.DateField', [], {'auto_now': 'True', 'null': 'True', 'blank': 'True'}),
|
||||
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '20', 'blank': 'True'}),
|
||||
'first_name_key': ('django.db.models.fields.CharField', [], {'max_length': '20', 'blank': 'True'}),
|
||||
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
|
||||
'last_name_key': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
|
||||
'middle_initial': ('django.db.models.fields.CharField', [], {'max_length': '4', 'null': 'True', 'blank': 'True'}),
|
||||
'middle_initial_key': ('django.db.models.fields.CharField', [], {'max_length': '4', 'null': 'True', 'blank': 'True'}),
|
||||
'modified_by': ('django.db.models.fields.CharField', [], {'max_length': '8', 'null': 'True', 'blank': 'True'}),
|
||||
'name_prefix': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}),
|
||||
'name_suffix': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}),
|
||||
'person_or_org_tag': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'record_type': ('django.db.models.fields.CharField', [], {'max_length': '8', 'null': 'True', 'blank': 'True'})
|
||||
},
|
||||
'idtracker.wgstatus': {
|
||||
'Meta': {'db_table': "'g_status'"},
|
||||
'status': ('django.db.models.fields.CharField', [], {'max_length': '25', 'db_column': "'status_value'"}),
|
||||
'status_id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
|
||||
},
|
||||
'idtracker.wgtype': {
|
||||
'Meta': {'db_table': "'g_type'"},
|
||||
'group_type_id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'type': ('django.db.models.fields.CharField', [], {'max_length': '25', 'db_column': "'group_type'"})
|
||||
},
|
||||
'wgchairs.protowriteup': {
|
||||
'date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now()'}),
|
||||
'draft': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.InternetDraft']"}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.PersonOrOrgInfo']"}),
|
||||
'writeup': ('django.db.models.fields.TextField', [], {})
|
||||
},
|
||||
'wgchairs.wgdelegate': {
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.PersonOrOrgInfo']"}),
|
||||
'wg': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.IETFWG']"})
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['wgchairs']
|
|
@ -1,87 +0,0 @@
|
|||
import datetime
|
||||
|
||||
from django.db import models
|
||||
from django.conf import settings
|
||||
|
||||
from ietf.idtracker.models import (IETFWG, PersonOrOrgInfo,
|
||||
InternetDraft)
|
||||
|
||||
|
||||
class WGDelegate(models.Model):
|
||||
person = models.ForeignKey(
|
||||
PersonOrOrgInfo,
|
||||
)
|
||||
|
||||
wg = models.ForeignKey(IETFWG, related_name="old_wgdelegate_set" if settings.USE_DB_REDESIGN_PROXY_CLASSES else None)
|
||||
|
||||
def __unicode__(self):
|
||||
return "%s" % self.person
|
||||
|
||||
class Meta:
|
||||
verbose_name = "WG Delegate"
|
||||
|
||||
class ProtoWriteUp(models.Model):
|
||||
person = models.ForeignKey(
|
||||
PersonOrOrgInfo,
|
||||
blank=False,
|
||||
null=False,
|
||||
)
|
||||
|
||||
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
|
||||
from ietf.idtracker.models import InternetDraftOld as InternetDraft
|
||||
|
||||
draft = models.ForeignKey(
|
||||
InternetDraft,
|
||||
blank=False,
|
||||
null=False,
|
||||
)
|
||||
|
||||
date = models.DateTimeField(
|
||||
default=datetime.datetime.now(),
|
||||
blank=False,
|
||||
null=False,
|
||||
)
|
||||
|
||||
writeup = models.TextField(
|
||||
blank=False,
|
||||
null=False,
|
||||
)
|
||||
|
||||
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
|
||||
from ietf.group.models import Role
|
||||
class WGDelegateProxy(Role):
|
||||
#person = models.ForeignKey(PersonOrOrgInfo) # same name
|
||||
#wg = models.ForeignKey(IETFWG)
|
||||
@property
|
||||
def wg(self):
|
||||
return self.group
|
||||
|
||||
def __unicode__(self):
|
||||
return u"%s" % self.person
|
||||
|
||||
class Meta:
|
||||
proxy = True
|
||||
|
||||
from ietf.doc.models import WriteupDocEvent
|
||||
class ProtoWriteUpProxy(WriteupDocEvent):
|
||||
#person = models.ForeignKey(PersonOrOrgInfo, blank=False, null=False)
|
||||
@property
|
||||
def person(self):
|
||||
return self.by
|
||||
#draft = models.ForeignKey(InternetDraft, blank=False, null=False)
|
||||
@property
|
||||
def draft(self):
|
||||
return self.doc
|
||||
#date = models.DateTimeField(default=datetime.datetime.now(), blank=False, null=False)
|
||||
@property
|
||||
def date(self):
|
||||
return self.time
|
||||
#writeup = models.TextField(blank=False, null=False)
|
||||
@property
|
||||
def writeup(self):
|
||||
return self.text
|
||||
class Meta:
|
||||
proxy = True
|
||||
|
||||
#WGDelegateOld = WGDelegate
|
||||
WGDelegate = WGDelegateProxy
|
1
ietf/wgchairs/templatetags/.gitignore
vendored
1
ietf/wgchairs/templatetags/.gitignore
vendored
|
@ -1 +0,0 @@
|
|||
/*.pyc
|
|
@ -1,47 +0,0 @@
|
|||
from django.conf import settings
|
||||
from django import template
|
||||
|
||||
from ietf.ietfworkflows.utils import get_state_for_draft
|
||||
from ietf.wgchairs.accounts import (can_manage_workflow_in_group,
|
||||
can_manage_delegates_in_group,
|
||||
can_manage_shepherds_in_group)
|
||||
|
||||
|
||||
register = template.Library()
|
||||
|
||||
|
||||
@register.inclusion_tag('wgchairs/wgchairs_admin_options.html', takes_context=True)
|
||||
def wgchairs_admin_options(context, wg):
|
||||
request = context.get('request', None)
|
||||
user = request and request.user
|
||||
return {'user': user,
|
||||
'can_manage_delegates': can_manage_delegates_in_group(user, wg),
|
||||
'can_manage_workflow': can_manage_workflow_in_group(user, wg),
|
||||
'can_manage_shepherds': can_manage_shepherds_in_group(user, wg),
|
||||
'wg': wg,
|
||||
'selected': context.get('selected', None),
|
||||
}
|
||||
|
||||
@register.simple_tag
|
||||
def writeup(doc):
|
||||
writeup = doc.protowriteup_set.all()
|
||||
if not writeup:
|
||||
return ''
|
||||
else:
|
||||
return writeup[0].writeup
|
||||
|
||||
|
||||
@register.simple_tag
|
||||
def writeupdate(doc):
|
||||
writeup = doc.protowriteup_set.all()
|
||||
if not writeup:
|
||||
return ''
|
||||
else:
|
||||
return writeup[0].date
|
||||
|
||||
|
||||
@register.inclusion_tag('wgchairs/draft_state.html', takes_context=True)
|
||||
def show_state(context, doc):
|
||||
return {'doc': doc,
|
||||
'state': get_state_for_draft(doc),
|
||||
}
|
|
@ -1,214 +0,0 @@
|
|||
import datetime, os, shutil
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.models import User
|
||||
from django.core.urlresolvers import reverse as urlreverse
|
||||
import django.test
|
||||
from StringIO import StringIO
|
||||
from pyquery import PyQuery
|
||||
|
||||
from ietf.utils.test_utils import login_testing_unauthorized
|
||||
from ietf.utils.test_data import make_test_data
|
||||
from ietf.utils.mail import outbox
|
||||
|
||||
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
|
||||
from ietf.person.models import Person, Email
|
||||
from ietf.group.models import Group, GroupHistory, Role, GroupStateTransitions
|
||||
from ietf.doc.models import Document, State, WriteupDocEvent
|
||||
from ietf.name.models import DocTagName
|
||||
|
||||
class ManageDelegatesTestCase(django.test.TestCase):
|
||||
fixtures = ['names']
|
||||
|
||||
def test_delete_delegate(self):
|
||||
make_test_data()
|
||||
|
||||
url = urlreverse('manage_delegates', kwargs=dict(acronym="mars"))
|
||||
login_testing_unauthorized(self, "secretary", url)
|
||||
|
||||
delegates = Role.objects.filter(name="delegate", group__acronym="mars")
|
||||
self.assertTrue(len(delegates) > 0)
|
||||
|
||||
# get
|
||||
r = self.client.get(url)
|
||||
self.assertEquals(r.status_code, 200)
|
||||
q = PyQuery(r.content)
|
||||
self.assertEquals(len(q('form input[name=delete]')), len(delegates))
|
||||
|
||||
# delete
|
||||
r = self.client.post(url,
|
||||
dict(remove="1",
|
||||
delete=[d.pk for d in delegates]))
|
||||
self.assertEquals(r.status_code, 200)
|
||||
q = PyQuery(r.content)
|
||||
self.assertEquals(len(q('form input[name=delete]')), 0)
|
||||
self.assertEquals(Role.objects.filter(name="delegate", group__acronym="mars").count(), 0)
|
||||
|
||||
def test_add_not_existing_delegate(self):
|
||||
make_test_data()
|
||||
|
||||
url = urlreverse('manage_delegates', kwargs=dict(acronym="mars"))
|
||||
login_testing_unauthorized(self, "secretary", url)
|
||||
|
||||
# get
|
||||
r = self.client.get(url)
|
||||
self.assertEquals(r.status_code, 200)
|
||||
q = PyQuery(r.content)
|
||||
self.assertEquals(len(q('form input[name=email]')), 1)
|
||||
|
||||
# add non-existing
|
||||
r = self.client.post(url,
|
||||
dict(email="unknown@example.com",
|
||||
form_type="single"))
|
||||
self.assertEquals(r.status_code, 200)
|
||||
self.assertTrue("unknown@example.com" in r.content)
|
||||
q = PyQuery(r.content)
|
||||
self.assertEquals(len(q('form input[type=submit][value*="Send email"]')), 1)
|
||||
|
||||
# we get back a warning and offer to send email, do that
|
||||
mailbox_before = len(outbox)
|
||||
r = self.client.post(url,
|
||||
dict(email="unknown@example.com",
|
||||
form_type="notexist"))
|
||||
self.assertEquals(r.status_code, 200)
|
||||
self.assertTrue("Email sent" in r.content)
|
||||
self.assertEquals(len(outbox), mailbox_before + 3)
|
||||
|
||||
def test_add_delegate(self):
|
||||
make_test_data()
|
||||
|
||||
url = urlreverse('manage_delegates', kwargs=dict(acronym="mars"))
|
||||
login_testing_unauthorized(self, "secretary", url)
|
||||
|
||||
# get
|
||||
r = self.client.get(url)
|
||||
self.assertEquals(r.status_code, 200)
|
||||
q = PyQuery(r.content)
|
||||
self.assertEquals(len(q('form input[name=email]')), 1)
|
||||
|
||||
# add existing person
|
||||
history_before = GroupHistory.objects.filter(acronym="mars").count()
|
||||
r = self.client.post(url,
|
||||
dict(email="plain@example.com",
|
||||
form_type="single"))
|
||||
self.assertEquals(r.status_code, 200)
|
||||
q = PyQuery(r.content)
|
||||
self.assertTrue("new delegate" in r.content)
|
||||
self.assertTrue(Email.objects.get(address="plain@example.com").person.plain_name() in r.content)
|
||||
self.assertEquals(Role.objects.filter(name="delegate", group__acronym="mars", email__address="plain@example.com").count(), 1)
|
||||
self.assertEquals(history_before + 1, GroupHistory.objects.filter(acronym="mars").count())
|
||||
|
||||
|
||||
class ManageShepherdsTestCase(django.test.TestCase):
|
||||
fixtures = ['names']
|
||||
|
||||
def test_manage_shepherds(self):
|
||||
make_test_data()
|
||||
|
||||
url = urlreverse('manage_shepherds', kwargs=dict(acronym="mars"))
|
||||
login_testing_unauthorized(self, "secretary", url)
|
||||
|
||||
# setup test documents
|
||||
group = Group.objects.get(acronym="mars")
|
||||
|
||||
from ietf.doc.models import Document
|
||||
common = dict(group=group,
|
||||
ad=Person.objects.get(user__username="ad"),
|
||||
type_id="draft")
|
||||
Document.objects.create(name="test-shepherd-no",
|
||||
title="No shepherd",
|
||||
shepherd=None,
|
||||
**common)
|
||||
Document.objects.create(name="test-shepherd-me",
|
||||
title="Shepherd me",
|
||||
shepherd=Person.objects.get(user__username="secretary"),
|
||||
**common)
|
||||
Document.objects.create(name="test-shepherd-other", title="Shepherd other",
|
||||
shepherd=Person.objects.get(user__username="plain"),
|
||||
**common)
|
||||
for d in Document.objects.filter(name__startswith="test-shepherd"):
|
||||
d.set_state(State.objects.get(used=True, type="draft", slug="active"))
|
||||
|
||||
# get and make sure they are divided correctly
|
||||
r = self.client.get(url)
|
||||
self.assertEquals(r.status_code, 200)
|
||||
q = PyQuery(r.content)
|
||||
self.assertEquals(len(q('div#noshepherd a:contains("No shepherd")')), 1)
|
||||
self.assertEquals(len(q('div#mydocs a:contains("Shepherd me")')), 1)
|
||||
self.assertEquals(len(q('div#othershepherds a:contains("Shepherd other")')), 1)
|
||||
|
||||
|
||||
class ManageWorkflowTestCase(django.test.TestCase):
|
||||
fixtures = ['names']
|
||||
|
||||
def test_manage_workflows(self):
|
||||
make_test_data()
|
||||
|
||||
group = Group.objects.get(acronym="mars")
|
||||
|
||||
url = urlreverse('manage_workflow', kwargs=dict(acronym=group.acronym))
|
||||
login_testing_unauthorized(self, "secretary", url)
|
||||
|
||||
state = State.objects.get(used=True, type="draft-stream-ietf", slug="wg-lc")
|
||||
self.assertTrue(state not in group.unused_states.all())
|
||||
|
||||
# get
|
||||
r = self.client.get(url)
|
||||
self.assertEquals(r.status_code, 200)
|
||||
q = PyQuery(r.content)
|
||||
self.assertEquals(len(q("form.set-state").find("input[name=state][value='%s']" % state.pk).parents("form").find("input[name=active][value='0']")), 1)
|
||||
|
||||
# deactivate state
|
||||
r = self.client.post(url,
|
||||
dict(action="setstateactive",
|
||||
state=state.pk,
|
||||
active="0"))
|
||||
self.assertEquals(r.status_code, 200)
|
||||
q = PyQuery(r.content)
|
||||
self.assertEquals(len(q("form.set-state").find("input[name=state][value='%s']" % state.pk).parents("form").find("input[name=active][value='1']")), 1)
|
||||
group = Group.objects.get(acronym=group.acronym)
|
||||
self.assertTrue(state in group.unused_states.all())
|
||||
|
||||
# change next states
|
||||
state = State.objects.get(used=True, type="draft-stream-ietf", slug="wg-doc")
|
||||
next_states = State.objects.filter(used=True, type=b"draft-stream-ietf", slug__in=["parked", "dead", "wait-wgw", 'sub-pub']).values_list('pk', flat=True)
|
||||
r = self.client.post(url,
|
||||
dict(action="setnextstates",
|
||||
state=state.pk,
|
||||
next_states=next_states))
|
||||
self.assertEquals(r.status_code, 200)
|
||||
q = PyQuery(r.content)
|
||||
self.assertEquals(len(q("form.set-next-states").find("input[name=state][value='%s']" % state.pk).parents('form').find("input[name=next_states][checked=checked]")), len(next_states))
|
||||
transitions = GroupStateTransitions.objects.filter(group=group, state=state)
|
||||
self.assertEquals(len(transitions), 1)
|
||||
self.assertEquals(set(transitions[0].next_states.values_list("pk", flat=True)), set(next_states))
|
||||
|
||||
# change them back to default
|
||||
next_states = state.next_states.values_list("pk", flat=True)
|
||||
r = self.client.post(url,
|
||||
dict(action="setnextstates",
|
||||
state=state.pk,
|
||||
next_states=next_states))
|
||||
self.assertEquals(r.status_code, 200)
|
||||
q = PyQuery(r.content)
|
||||
transitions = GroupStateTransitions.objects.filter(group=group, state=state)
|
||||
self.assertEquals(len(transitions), 0)
|
||||
|
||||
# deactivate tag
|
||||
tag = DocTagName.objects.get(slug="w-expert")
|
||||
r = self.client.post(url,
|
||||
dict(action="settagactive",
|
||||
tag=tag.pk,
|
||||
active="0"))
|
||||
self.assertEquals(r.status_code, 200)
|
||||
q = PyQuery(r.content)
|
||||
self.assertEquals(len(q('form').find('input[name=tag][value="%s"]' % tag.pk).parents("form").find("input[name=active]")), 1)
|
||||
group = Group.objects.get(acronym=group.acronym)
|
||||
self.assertTrue(tag in group.unused_tags.all())
|
||||
|
||||
if not settings.USE_DB_REDESIGN_PROXY_CLASSES:
|
||||
# the above tests only work with the new schema
|
||||
del ManageDelegatesTestCase
|
||||
del ManageShepherdsTestCase
|
||||
del ManageWorkflowTestCase
|
||||
del ManageWriteupCase
|
|
@ -1,7 +0,0 @@
|
|||
# Copyright The IETF Trust 2008, All Rights Reserved
|
||||
|
||||
from django.conf.urls.defaults import patterns, url
|
||||
|
||||
urlpatterns = patterns('ietf.wgchairs.views',
|
||||
url(r'^delegates/$', 'manage_delegates', name='manage_delegates'),
|
||||
)
|
|
@ -1,73 +0,0 @@
|
|||
from django.conf import settings
|
||||
from ietf.idtracker.models import IETFWG, InternetDraft
|
||||
from django.shortcuts import get_object_or_404, render_to_response
|
||||
from django.template import RequestContext
|
||||
from django.http import HttpResponseForbidden, Http404
|
||||
|
||||
from ietf.wgchairs.forms import (RemoveDelegateForm, add_form_factory,
|
||||
workflow_form_factory, TransitionFormSet,
|
||||
WriteUpEditForm, assign_shepherd)
|
||||
from ietf.wgchairs.accounts import (can_manage_delegates_in_group, get_person_for_user,
|
||||
can_manage_shepherds_in_group,
|
||||
can_manage_workflow_in_group,
|
||||
can_manage_shepherd_of_a_document,
|
||||
can_manage_writeup_of_a_document,
|
||||
can_manage_writeup_of_a_document_no_state,
|
||||
)
|
||||
from ietf.ietfworkflows.constants import REQUIRED_STATES
|
||||
from ietf.ietfworkflows.utils import (get_workflow_for_wg,
|
||||
get_default_workflow_for_wg,
|
||||
get_state_by_name,
|
||||
get_annotation_tags_for_draft,
|
||||
get_state_for_draft, WAITING_WRITEUP,
|
||||
FOLLOWUP_TAG)
|
||||
from ietf.name.models import DocTagName
|
||||
from ietf.doc.models import State
|
||||
from ietf.doc.utils import get_tags_for_stream_id
|
||||
|
||||
def manage_delegates(request, acronym):
|
||||
wg = get_object_or_404(IETFWG, group_acronym__acronym=acronym, group_type=1)
|
||||
user = request.user
|
||||
if not can_manage_delegates_in_group(user, wg):
|
||||
return HttpResponseForbidden('You have no permission to access this view')
|
||||
delegates = wg.wgdelegate_set.all()
|
||||
add_form = add_form_factory(request, wg, user)
|
||||
if request.method == 'POST':
|
||||
if request.POST.get('remove', None):
|
||||
form = RemoveDelegateForm(wg=wg, data=request.POST.copy())
|
||||
if form.is_valid():
|
||||
form.save()
|
||||
elif add_form.is_valid():
|
||||
add_form.save()
|
||||
add_form = add_form.get_next_form()
|
||||
max_delegates = getattr(settings, 'MAX_WG_DELEGATES', 3)
|
||||
return render_to_response('wgchairs/manage_delegates.html',
|
||||
{'wg': wg,
|
||||
'delegates': delegates,
|
||||
'selected': 'manage_delegates',
|
||||
'can_add': delegates.count() < max_delegates,
|
||||
'max_delegates': max_delegates,
|
||||
'add_form': add_form,
|
||||
}, RequestContext(request))
|
||||
|
||||
|
||||
def wg_shepherd_documents(request, acronym):
|
||||
wg = get_object_or_404(IETFWG, group_acronym__acronym=acronym, group_type=1)
|
||||
user = request.user
|
||||
if not can_manage_shepherds_in_group(user, wg):
|
||||
return HttpResponseForbidden('You have no permission to access this view')
|
||||
current_person = get_person_for_user(user)
|
||||
|
||||
base_qs = InternetDraft.objects.filter(group=wg, states__type="draft", states__slug="active").select_related("status").order_by('title')
|
||||
documents_no_shepherd = base_qs.filter(shepherd=None)
|
||||
documents_my = base_qs.filter(shepherd=current_person)
|
||||
documents_other = base_qs.exclude(shepherd=None).exclude(shepherd__pk__in=[current_person.pk, 0])
|
||||
context = {
|
||||
'no_shepherd': documents_no_shepherd,
|
||||
'my_documents': documents_my,
|
||||
'other_shepherds': documents_other,
|
||||
'selected': 'manage_shepherds',
|
||||
'wg': wg,
|
||||
}
|
||||
return render_to_response('wgchairs/wg_shepherd_documents.html', context, RequestContext(request))
|
||||
|
Loading…
Reference in a new issue