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:
Ole Laursen 2013-09-19 15:22:59 +00:00
parent 19fc7c14bc
commit a871d6e19e
33 changed files with 15 additions and 2016 deletions

View file

@ -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 ","}')"

View file

@ -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

View file

@ -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

View file

@ -175,7 +175,6 @@ INSTALLED_APPS = (
'ietf.wginfo',
'ietf.submit',
'ietf.ietfworkflows',
'ietf.wgchairs',
'ietf.wgcharter',
'ietf.sync',
'ietf.community',

View file

@ -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 %}

View file

@ -1 +0,0 @@
{{ state.name }}

View file

@ -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 %}

View file

@ -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 %}

View file

@ -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 %}

View file

@ -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 %}

View file

@ -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>

View file

@ -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 %}

View file

@ -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 %}

View file

@ -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%}

View file

@ -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>

View file

@ -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 %}

View file

@ -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 %}

View file

@ -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 &#187;</a> |
{% endif %}
<a href="http://tools.ietf.org/wg/{{ wg.group_acronym.acronym }}/">Tools WG Page &#187;</a>
</div>
{% block wg_content %}
{% endblock wg_content %}
</div>
{% endblock content %}

View file

@ -1 +0,0 @@
/*.pyc

View file

@ -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)

View file

@ -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)

View file

@ -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()

View file

@ -1 +0,0 @@
/*.pyc

View file

@ -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']

View file

@ -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']

View file

@ -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

View file

@ -1 +0,0 @@
/*.pyc

View file

@ -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),
}

View file

@ -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

View file

@ -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'),
)

View file

@ -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))