parent
f72b0a1c93
commit
abb74d9977
|
@ -4,15 +4,21 @@ from email.utils import parseaddr
|
|||
from django import forms
|
||||
from django.conf import settings
|
||||
from django.forms.util import ErrorList
|
||||
from django.db.models import Q
|
||||
from django.forms.widgets import RadioFieldRenderer
|
||||
from django.core.validators import validate_email, ValidationError
|
||||
from django.template.loader import render_to_string
|
||||
from django.utils.html import format_html
|
||||
from django.utils.encoding import force_text
|
||||
from django.utils.safestring import mark_safe
|
||||
|
||||
|
||||
from ietf.liaisons.accounts import (can_add_outgoing_liaison, can_add_incoming_liaison,
|
||||
get_person_for_user, is_secretariat, is_sdo_liaison_manager)
|
||||
from ietf.liaisons.utils import IETFHM
|
||||
from ietf.liaisons.widgets import (FromWidget, ReadOnlyWidget, ButtonWidget,
|
||||
ShowAttachmentsWidget, RelatedLiaisonWidget)
|
||||
from ietf.liaisons.models import LiaisonStatement, LiaisonStatementPurposeName
|
||||
from ietf.liaisons.models import LiaisonStatement, LiaisonStatementPurposeName, LiaisonStatementEvent
|
||||
from ietf.group.models import Group, Role
|
||||
from ietf.person.models import Person, Email
|
||||
from ietf.doc.models import Document
|
||||
|
@ -468,3 +474,63 @@ def liaison_form_factory(request, **kwargs):
|
|||
return IncomingLiaisonForm(user, **kwargs)
|
||||
return None
|
||||
|
||||
|
||||
class RadioRenderer(RadioFieldRenderer):
|
||||
|
||||
def render(self):
|
||||
output = []
|
||||
for widget in self:
|
||||
output.append(format_html(force_text(widget)))
|
||||
return mark_safe('\n'.join(output))
|
||||
|
||||
|
||||
class SearchLiaisonForm(forms.Form):
|
||||
|
||||
text = forms.CharField(required=False)
|
||||
scope = forms.ChoiceField(choices=(("all", "All text fields"), ("title", "Title field")), required=False, initial='title', widget=forms.RadioSelect(renderer=RadioRenderer))
|
||||
source = forms.CharField(required=False)
|
||||
destination = forms.CharField(required=False)
|
||||
start_date = forms.DateField(required=False, help_text="Format: YYYY-MM-DD")
|
||||
end_date = forms.DateField(required=False, help_text="Format: YYYY-MM-DD")
|
||||
|
||||
def get_results(self):
|
||||
results = LiaisonStatement.objects.filter(state__slug='approved').extra(
|
||||
select={
|
||||
'_submitted': 'SELECT time FROM liaisons_liaisonstatementevent WHERE liaisons_liaisonstatement.id = liaisons_liaisonstatementevent.statement_id AND liaisons_liaisonstatementevent.type_id = "submit"',
|
||||
'from_concat': 'SELECT GROUP_CONCAT(name SEPARATOR ", ") FROM group_group JOIN liaisons_liaisonstatement_from_groups WHERE liaisons_liaisonstatement.id = liaisons_liaisonstatement_from_groups.liaisonstatement_id AND liaisons_liaisonstatement_from_groups.group_id = group_group.id',
|
||||
'to_concat': 'SELECT GROUP_CONCAT(name SEPARATOR ", ") FROM group_group JOIN liaisons_liaisonstatement_to_groups WHERE liaisons_liaisonstatement.id = liaisons_liaisonstatement_to_groups.liaisonstatement_id AND liaisons_liaisonstatement_to_groups.group_id = group_group.id',
|
||||
})
|
||||
if self.is_bound:
|
||||
query = self.cleaned_data.get('text')
|
||||
if query:
|
||||
if self.cleaned_data.get('scope') == 'title':
|
||||
q = Q(title__icontains=query)
|
||||
else:
|
||||
q = (Q(title__icontains=query) | Q(other_identifiers__icontains=query) | Q(body__icontains=query) | Q(attachments__title__icontains=query) |
|
||||
Q(response_contacts__icontains=query) | Q(technical_contacts__icontains=query) | Q(action_holder_contacts__icontains=query) |
|
||||
Q(cc_contacts=query))
|
||||
results = results.filter(q)
|
||||
source = self.cleaned_data.get('source')
|
||||
if source:
|
||||
results = results.filter(Q(from_groups__name__icontains=source) | Q(from_groups__acronym__iexact=source) | Q(from_name__icontains=source))
|
||||
destination = self.cleaned_data.get('destination')
|
||||
if destination:
|
||||
results = results.filter(Q(to_groups__name__icontains=destination) | Q(to_groups__acronym__iexact=destination) | Q(to_name__icontains=destination))
|
||||
start_date = self.cleaned_data.get('start_date')
|
||||
end_date = self.cleaned_data.get('end_date')
|
||||
events = None
|
||||
if start_date:
|
||||
events = LiaisonStatementEvent.objects.filter(type='submit', time__gte=start_date)
|
||||
if end_date:
|
||||
events = events.filter(time__lte=end_date)
|
||||
elif end_date:
|
||||
events = LiaisonStatementEvent.objects.filter(type='submit', time__lte=end_date)
|
||||
if events:
|
||||
results = results.filter(liaisonstatementevent__in=events)
|
||||
|
||||
|
||||
destination = self.cleaned_data.get('destination')
|
||||
if destination:
|
||||
results = results.filter(Q(to_groups__name__icontains=destination) | Q(to_groups__acronym__iexact=destination) | Q(to_name__icontains=destination))
|
||||
results = results.distinct().order_by('title')
|
||||
return results
|
||||
|
|
|
@ -36,6 +36,8 @@ class LiaisonStatement(models.Model):
|
|||
|
||||
attachments = models.ManyToManyField(Document, through='LiaisonStatementAttachments', blank=True)
|
||||
|
||||
state = models.ForeignKey(LiaisonStatementState, default='pending')
|
||||
|
||||
def name(self):
|
||||
if self.from_group:
|
||||
frm = self.from_group.acronym or self.from_group.name
|
||||
|
@ -50,6 +52,23 @@ class LiaisonStatement(models.Model):
|
|||
def __unicode__(self):
|
||||
return self.title or u"<no title>"
|
||||
|
||||
@property
|
||||
def submitted(self):
|
||||
if getattr(self, '_submitted', None):
|
||||
return self._submitted
|
||||
event = self.liaisonstatementevent_set.filter(type__slug='submit')
|
||||
if event.count():
|
||||
return event[0].time
|
||||
return None
|
||||
|
||||
@property
|
||||
def approved(self):
|
||||
return self.state_id == 'approved'
|
||||
|
||||
@property
|
||||
def action_taken(self):
|
||||
return bool(self.tags.filter(slug='taken').count())
|
||||
|
||||
|
||||
class LiaisonStatementAttachments(models.Model):
|
||||
statement = models.ForeignKey(LiaisonStatement)
|
||||
|
|
|
@ -13,7 +13,7 @@ can_submit_liaison_required = passes_test_decorator(
|
|||
"Restricted to participants who are authorized to submit liaison statements on behalf of the various IETF entities")
|
||||
|
||||
def approvable_liaison_statements(user):
|
||||
liaisons = LiaisonStatement.objects.filter(approved=None)
|
||||
liaisons = LiaisonStatement.objects.filter(state__slug='pending')
|
||||
if has_role(user, "Secretariat"):
|
||||
return liaisons
|
||||
|
||||
|
@ -28,7 +28,7 @@ def approvable_liaison_statements(user):
|
|||
else:
|
||||
group_acronyms.append(x)
|
||||
|
||||
return liaisons.filter(Q(from_group__acronym__in=group_acronyms) | Q(from_group__pk__in=group_ids))
|
||||
return liaisons.filter(Q(from_groups__acronym__in=group_acronyms) | Q(from_groups__pk__in=group_ids))
|
||||
|
||||
|
||||
# the following is a biggish object hierarchy abstracting the entity
|
||||
|
|
|
@ -13,7 +13,7 @@ from ietf.liaisons.accounts import (get_person_for_user, can_add_outgoing_liaiso
|
|||
can_add_incoming_liaison,
|
||||
is_ietfchair, is_iabchair, is_iab_executive_director,
|
||||
can_edit_liaison, is_secretariat)
|
||||
from ietf.liaisons.forms import liaison_form_factory
|
||||
from ietf.liaisons.forms import liaison_form_factory, SearchLiaisonForm
|
||||
from ietf.liaisons.utils import IETFHM, can_submit_liaison_required, approvable_liaison_statements
|
||||
from ietf.liaisons.mails import notify_pending_by_email, send_liaison_by_email
|
||||
|
||||
|
@ -85,7 +85,7 @@ def get_info(request):
|
|||
def normalize_sort(request):
|
||||
sort = request.GET.get('sort', "")
|
||||
if sort not in ('submitted', 'deadline', 'title', 'to_name', 'from_name'):
|
||||
sort = "submitted"
|
||||
sort = "id"
|
||||
|
||||
# reverse dates
|
||||
order_by = "-" + sort if sort in ("submitted", "deadline") else sort
|
||||
|
@ -93,8 +93,15 @@ def normalize_sort(request):
|
|||
return sort, order_by
|
||||
|
||||
def liaison_list(request):
|
||||
sort, order_by = normalize_sort(request)
|
||||
liaisons = LiaisonStatement.objects.exclude(approved=None).order_by(order_by).prefetch_related("attachments")
|
||||
if request.GET.get('search', None):
|
||||
form = SearchLiaisonForm(data=request.GET)
|
||||
if form.is_valid():
|
||||
result = form.get_results()
|
||||
else:
|
||||
form = SearchLiaisonForm()
|
||||
result = form.get_results()
|
||||
|
||||
liaisons = result
|
||||
|
||||
can_send_outgoing = can_add_outgoing_liaison(request.user)
|
||||
can_send_incoming = can_add_incoming_liaison(request.user)
|
||||
|
@ -107,7 +114,8 @@ def liaison_list(request):
|
|||
"approvable": approvable,
|
||||
"can_send_incoming": can_send_incoming,
|
||||
"can_send_outgoing": can_send_outgoing,
|
||||
"sort": sort,
|
||||
"with_search": True,
|
||||
"form": form,
|
||||
}, context_instance=RequestContext(request))
|
||||
|
||||
def ajax_liaison_list(request):
|
||||
|
@ -121,7 +129,7 @@ def ajax_liaison_list(request):
|
|||
|
||||
@can_submit_liaison_required
|
||||
def liaison_approval_list(request):
|
||||
liaisons = approvable_liaison_statements(request.user).order_by("-submitted")
|
||||
liaisons = approvable_liaison_statements(request.user).order_by("-id")
|
||||
|
||||
return render_to_response('liaisons/approval_list.html', {
|
||||
"liaisons": liaisons,
|
||||
|
@ -184,7 +192,7 @@ def _find_person_in_emails(liaison, person):
|
|||
|
||||
|
||||
def liaison_detail(request, object_id):
|
||||
liaison = get_object_or_404(LiaisonStatement.objects.exclude(approved=None), pk=object_id)
|
||||
liaison = get_object_or_404(LiaisonStatement.objects.filter(state__slug='approved'), pk=object_id)
|
||||
can_edit = request.user.is_authenticated() and can_edit_liaison(request.user, liaison)
|
||||
can_take_care = _can_take_care(liaison, request.user)
|
||||
|
||||
|
@ -193,7 +201,7 @@ def liaison_detail(request, object_id):
|
|||
liaison.save()
|
||||
can_take_care = False
|
||||
|
||||
relations = liaison.liaisonstatement_set.exclude(approved=None)
|
||||
relations = liaison.source_of_set.filter(target__state__slug='approved')
|
||||
|
||||
return render_to_response("liaisons/detail.html", {
|
||||
"liaison": liaison,
|
||||
|
|
|
@ -1,21 +1,24 @@
|
|||
{% load ietf_filters %}
|
||||
|
||||
<table class="ietf-table" width="100%">
|
||||
<table class="ietf-table" width="100%" id="LiaisonListTable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th width="9%" class="sort{% if sort == "submitted" %} sorted{% endif %}"><a href="?sort=submitted">Date</a></th>
|
||||
<th width="15%" class="sort{% if sort == "from_name" %} sorted{% endif %}"><a href="?sort=from_name">From</a></th>
|
||||
<th width="15%" class="sort{% if sort == "to_name" %} sorted{% endif %}"><a href="?sort=to_name">To</a></th>
|
||||
<th width="9%" class="sort{% if sort == "deadline" %} sorted{% endif %}"><a href="?sort=deadline">Deadline</a></th>
|
||||
<th width="50%" class="sort{% if sort == "title" %} sorted{% endif %}"><a href="?sort=title">Title</a></th>
|
||||
<th width="9%" class="sort{% if sort == "submitted" %} sorted{% endif %}">Date</th>
|
||||
<th width="15%" class="sort{% if sort == "from_name" %} sorted{% endif %}">From</th>
|
||||
<th width="15%" class="sort{% if sort == "to_name" %} sorted{% endif %}">To</th>
|
||||
<th width="9%" class="sort{% if sort == "deadline" %} sorted{% endif %}">Deadline</th>
|
||||
<th width="50%" class="sort{% if sort == "title" %} sorted{% endif %}">Title</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
{% for liaison in liaisons %}
|
||||
<tr class="{% cycle oddrow,evenrow %}">
|
||||
<td style="white-space:nowrap;">{{ liaison.submitted|date:"Y-m-d" }}</td>
|
||||
<td>{{ liaison.from_name }}</td>
|
||||
<td>{{ liaison.from_concat|default:liaison.from_name }}</td>
|
||||
<td>
|
||||
{% if liaison.from_contact_id %}
|
||||
{{ liaison.to_name }}
|
||||
{% if liaison.to_concat %}
|
||||
{{ liaison.to_concat }}
|
||||
{% else %}
|
||||
{{ liaison.to_name|strip_email }}
|
||||
{% endif %}
|
||||
|
@ -35,5 +38,5 @@
|
|||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
|
|
|
@ -23,7 +23,12 @@
|
|||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% if with_search %}
|
||||
<div class="ietf-box search-form-box">
|
||||
{% include "liaisons/search_form.html" %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% include "liaisons/liaison_table.html" %}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
|
|
15
ietf/templates/liaisons/search_form.html
Normal file
15
ietf/templates/liaisons/search_form.html
Normal file
|
@ -0,0 +1,15 @@
|
|||
<form id="search_form" class="search_form" action="{% url "liaison_list" %}" method="get">
|
||||
|
||||
<table>
|
||||
<tr><td><label>Search text:</label></td><td colspan="3">{{ form.text }}</td></tr>
|
||||
<tr><td><label>Search text scope:</label></td><td colspan="3">{{ form.scope }}</td></tr>
|
||||
<tr><td colspan="4"> </td></tr>
|
||||
<tr><td><label>Source:</label></td><td>{{ form.source }}</td><td><label>Destination:</label></td><td>{{ form.destination }}</td></tr>
|
||||
<tr><td><label>From date:</label><div class="help">{{ form.start_date.help_text }}</div></td><td>{{ form.start_date }}{{ form.errors.start_date }}</td><td><label>To date:</label><div class="help">{{ form.start_date.help_text }}</div></td><td>{{ form.end_date }}{{ form.errors.end_date }}</td></tr>
|
||||
</table>
|
||||
|
||||
<div class="submit">
|
||||
<input type="submit" class="button" name="search" value="Search"/>
|
||||
</div>
|
||||
|
||||
</form>
|
Loading…
Reference in a new issue