diff --git a/ietf/idtracker/models.py b/ietf/idtracker/models.py index 4bccac7e0..a02f09e56 100644 --- a/ietf/idtracker/models.py +++ b/ietf/idtracker/models.py @@ -156,10 +156,7 @@ class InternetDraft(models.Model): def idstate(self): idinternal = self.idinternal if idinternal: - if idinternal.cur_sub_state: - return "%s :: %s" % ( idinternal.cur_state, idinternal.cur_sub_state ) - else: - return idinternal.cur_state + return idinternal.docstate() else: return "I-D Exists" def revision_display(self): @@ -200,13 +197,7 @@ class PersonOrOrgInfo(models.Model): super(PersonOrOrgInfo, self).save() def __str__(self): if self.first_name == '' and self.last_name == '': - try: - postal = self.postaladdress_set.get(address_priority=1) - except PostalAddress.DoesNotExist: - return "PersonOrOrgInfo with no name, no postal address!" - except AssertionError: - return "PersonOrOrgInfo with multiple priority-1 addresses!" - return "%s" % ( postal.affiliated_company or postal.department or "???" ) + return self.affiliation() return "%s %s" % ( self.first_name or "", self.last_name or "") def email(self, priority=1, type='INET'): name = str(self) @@ -216,13 +207,13 @@ class PersonOrOrgInfo(models.Model): email = '' return (name, email) # Added by Sunny Lee to display person's affiliation - 5/26/2007 - def affiliation(self, priority=1, type='INET'): + def affiliation(self, priority=1): try: - postal = self.postaladdress_set.get(address_priority=1) + postal = self.postaladdress_set.get(address_priority=priority) except PostalAddress.DoesNotExist: - return "PersonOrOrgInfo with no name, no postal address!" + return "PersonOrOrgInfo with no postal address!" except AssertionError: - return "PersonOrOrgInfo with multiple priority-1 addresses!" + return "PersonOrOrgInfo with multiple priority-%d addresses!" % priority return "%s" % ( postal.affiliated_company or postal.department or "???" ) class Meta: db_table = 'person_or_org_info' @@ -331,7 +322,11 @@ class Rfc(models.Model): self.rfc_name_key = self.title.upper() super(Rfc, self).save() def displayname(self): - return "rfc%d.txt" % ( self.rfc_number ) + return "%s.txt" % ( self.filename() ) + def filename(self): + return "rfc%d" % ( self.rfc_number ) + def revision(self): + return "RFC" def doclink(self): return "http://www.ietf.org/rfc/%s" % ( self.displayname() ) class Meta: @@ -405,6 +400,10 @@ class IDInternal(models.Model): field is defined as a FK to InternetDrafts. One side effect of this is that select_related() will only work with rfc_flag=0. + + When searching where matches may be either I-Ds or RFCs, + you cannot use draft__ as that will cause an INNER JOIN + which will limit the responses to I-Ds. """ draft = models.ForeignKey(InternetDraft, primary_key=True, unique=True, db_column='id_document_tag') rfc_flag = models.IntegerField(null=True) @@ -457,8 +456,15 @@ class IDInternal(models.Model): return self.documentcomment_set.all().filter(rfc_flag=self.rfc_flag).order_by('-comment_date','-comment_time') def ballot_set(self): return IDInternal.objects.filter(ballot=self.ballot_id) + def ballot_primary(self): + return IDInternal.objects.filter(ballot=self.ballot_id,primary_flag=1) def ballot_others(self): return IDInternal.objects.filter(models.Q(primary_flag=0)|models.Q(primary_flag__isnull=True), ballot=self.ballot_id) + def docstate(self): + if self.cur_sub_state_id > 0: + return "%s :: %s" % ( self.cur_state, self.cur_sub_state ) + else: + return self.cur_state class Meta: db_table = 'id_internal' verbose_name = 'IDTracker Draft' diff --git a/ietf/idtracker/urls.py b/ietf/idtracker/urls.py index e3c15f0f4..4f1526d83 100644 --- a/ietf/idtracker/urls.py +++ b/ietf/idtracker/urls.py @@ -29,14 +29,14 @@ urlpatterns += patterns('', urlpatterns += patterns('django.views.generic.list_detail', (r'^rfc(?P\d+)/$', 'object_detail', rfc_dict), (r'^(?P\d+)/$', 'object_detail', id_dict), - (r'^(?P[^/]+)/$', 'object_detail', dict(id_dict, slug_field='draft__filename')), - (r'^comment/(?P\d+)/$', 'object_detail', comment_dict), - (r'^ballot/(?P\d+)/$', 'object_detail', ballot_dict), ) urlpatterns += patterns('', + (r'^(?P[^/]+)/$', views.view_id, dict(id_dict, slug_field='draft__filename')), + (r'^comment/(?P\d+)/$', views.view_comment, comment_dict), + (r'^ballot/(?P\d+)/$', views.view_ballot, ballot_dict), (r'^(?P[^/]+)/comment/(?P\d+)/$', views.comment, comment_dict), (r'^states/(?P\d+)/$', views.state_desc), (r'^states/substate/(?P\d+)/$', views.state_desc, { 'is_substate': 1 }), - (r'^(?P\d+)/edit/$', views.edit_idinternal), + #(r'^(?P\d+)/edit/$', views.edit_idinternal), (r'^$', views.search), ) diff --git a/ietf/idtracker/views.py b/ietf/idtracker/views.py index 8368172d1..1e467f799 100644 --- a/ietf/idtracker/views.py +++ b/ietf/idtracker/views.py @@ -5,7 +5,7 @@ from django.template import RequestContext, Context, loader from django.shortcuts import get_object_or_404, render_to_response from django.db.models import Q from django.views.generic.list_detail import object_detail, object_list -from ietf.idtracker.models import InternetDraft, IDInternal, IDState, IDSubState +from ietf.idtracker.models import InternetDraft, IDInternal, IDState, IDSubState, Rfc from ietf.idtracker.forms import EmailFeedback from ietf.utils.mail import send_mail_text @@ -22,54 +22,56 @@ def myfields(f): return f.formfield() def search(request): + # todo: check if these field names work for backwards + # compatability InternetDraftForm = forms.models.form_for_model(InternetDraft, formfield_callback=myfields) - idform = InternetDraftForm(request.POST) + idform = InternetDraftForm(request.REQUEST) InternalForm = forms.models.form_for_model(IDInternal, formfield_callback=myfields) - form = InternalForm(request.POST) - t = loader.get_template('idtracker/idtracker_search.html') + form = InternalForm(request.REQUEST) # if there's a post, do the search and supply results to the template - if request.method == 'POST': - qdict = { 'filename': 'draft__filename__contains', - 'job_owner': 'job_owner', - 'group': 'draft__group__acronym', - 'cur_state': 'cur_state', - 'cur_sub_state': 'cur_sub_state', - 'rfc_number': 'draft__rfc_number', - 'area_acronym': 'area_acronym', - 'note': 'note__contains', - } - q_objs = [Q(**{qdict[k]: request.POST[k]}) - for k in qdict.keys() - if request.POST[k] != ''] - matches = IDInternal.objects.all().filter(*q_objs) -# matches = IDInternal.objects.all() -# if request.POST['filename']: -# matches = matches.filter(draft__filename__contains=request.POST["filename"]) -# if request.POST['job_owner']: -# matches = matches.filter(job_owner=request.POST['job_owner']) -# if request.POST['group']: -# matches = matches.filter(draft__group__acronym=request.POST['group_acronym']) -# if request.POST['cur_state']: -# matches = matches.filter(cur_state=request.POST['cur_state']) -# if request.POST['cur_sub_state']: -# matches = matches.filter(cur_sub_state=request.POST['cur_sub_state']) -# if request.POST['rfc_number']: -# matches = matches.filter(draft__rfc_number=request.POST['rfc_number']) -# if request.POST['area_acronym']: -# matches = matches.filter(area_acronym=request.POST['area_acronym']) -# if request.POST['note']: -# matches = matches.filter(note__contains=request.POST['note']) + searching = False + # filename, rfc_number, group searches are seperate because + # they can't be represented as simple searches in the data model. + qdict = { + 'job_owner': 'job_owner', + 'cur_state': 'cur_state', + 'cur_sub_state': 'cur_sub_state', + 'area_acronym': 'area_acronym', + 'note': 'note__icontains', + } + q_objs = [] + for k in qdict.keys() + ['group', 'rfc_number', 'filename']: + if request.REQUEST.has_key(k): + searching = True + if request.REQUEST[k] != '' and qdict.has_key(k): + q_objs.append(Q(**{qdict[k]: request.REQUEST[k]})) + if searching: + group = request.REQUEST.get('group', '') + if group != '': + rfclist = [rfc.rfc_number for rfc in Rfc.objects.all().filter(group_acronym=group)] + draftlist = [draft.id_document_tag for draft in InternetDraft.objects.all().filter(group__acronym=group)] + q_objs.append(Q(draft__in=draftlist)&Q(rfc_flag=0)|Q(draft__in=rfclist)&Q(rfc_flag=1)) + rfc_number = request.REQUEST.get('rfc_number', '') + if rfc_number != '': + draftlist = [draft.id_document_tag for draft in InternetDraft.objects.all().filter(rfc_number=rfc_number)] + q_objs.append(Q(draft__in=draftlist)&Q(rfc_flag=0)|Q(draft=rfc_number)&Q(rfc_flag=1)) + filename = request.REQUEST.get('filename', '') + if filename != '': + draftlist = [draft.id_document_tag for draft in InternetDraft.objects.all().filter(filename__icontains=filename)] + q_objs.append(Q(draft__in=draftlist,rfc_flag=0)) + matches = IDInternal.objects.all().filter(*q_objs).filter(primary_flag=1) matches = matches.order_by('cur_state', 'cur_sub_state_id') else: matches = None - c = RequestContext(request, { + return render_to_response('idtracker/idtracker_search.html', { 'form': form, 'idform': idform, 'matches': matches, - }) - return HttpResponse(t.render(c)) + 'searching': searching, + }, context_instance=RequestContext(request)) +# proof of concept, orphaned for now def edit_idinternal(request, id=None): #draft = InternetDraft.objects.get(pk=id) draft = get_object_or_404(InternetDraft.objects, pk=id) @@ -89,14 +91,11 @@ def edit_idinternal(request, id=None): else: form = None - t = loader.get_template('idtracker/idtracker_edit.html') - - c = RequestContext(request, { + return render_to_response('idtracker/idtracker_edit.html', { 'form': form, 'idform': idform, 'draft': draft, - }) - return HttpResponse(t.render(c)) + }, context_instance=RequestContext(request)) def state_desc(request, state, is_substate=0): if int(state) == 100: @@ -142,3 +141,15 @@ def status(request): def last_call(request): queryset = IDInternal.objects.filter(primary_flag=1).filter(cur_state__state__in=('In Last Call', 'Waiting for Writeup', 'Waiting for AD Go-Ahead')).order_by('cur_state', 'status_date', 'ballot_id') return object_list(request, template_name="idtracker/status_of_items.html", queryset=queryset, extra_context={'title': 'Documents in Last Call'}) + +# Wrappers around object_detail to give permalink a handle. +# The named-URLs feature in django 0.97 will eliminate the +# need for these. +def view_id(*args, **kwargs): + return object_detail(*args, **kwargs) + +def view_comment(*args, **kwargs): + return object_detail(*args, **kwargs) + +def view_ballot(*args, **kwargs): + return object_detail(*args, **kwargs) diff --git a/ietf/templates/idtracker/base.html b/ietf/templates/idtracker/base.html index 2447881df..9cde6ddd4 100644 --- a/ietf/templates/idtracker/base.html +++ b/ietf/templates/idtracker/base.html @@ -22,6 +22,19 @@ {% block idcontent %} {% endblock %} +
+ Made with Django. +
+

+Did you find a bug? Let us know. +

+Any question or suggestion? +

+This page produced by the IETF Secretariat +for the IESG +

+ + {% include "debug.html" %} diff --git a/ietf/templates/idtracker/idinternal_detail.html b/ietf/templates/idtracker/idinternal_detail.html index 5c71870a5..f77859270 100644 --- a/ietf/templates/idtracker/idinternal_detail.html +++ b/ietf/templates/idtracker/idinternal_detail.html @@ -12,8 +12,7 @@

Detail Info
- {% if object.ballot_set|length_is:"1" %} - {% else %} + {% if object.ballot_others %} @@ -55,13 +54,16 @@ - {# what's the "if" here #}
- IESG evaluation record + {% if object.ballot.ballot_issued %} + IESG evaluation record [What they mean] [How they are recorded] + {% else %} + No IESG evaluation record + {% endif %}
@@ -187,7 +189,7 @@
-
+
@@ -201,17 +203,19 @@
- {% if object.ballot_set|length_is:"1" %} - {% else %} + {% if object.ballot_others %}

Actions

+ {# this "regroup" is to get the data structure into the shape + # that search_result_table wants - it doesn't do anything real. #} + {% regroup object.ballot_primary by docstate as grouped %} + {% include "idtracker/search_result_table.html" %}
{% endif %} -

Comment Log

@@ -235,18 +239,22 @@ *{{ comment.get_ballot_display }}*] {% endif %} {{ comment.comment_text|format_textarea|truncatewords_html:"25" }} - + + {% endfor %}
-
+ + +
- -

-
+ diff --git a/ietf/templates/idtracker/idtracker_search.html b/ietf/templates/idtracker/idtracker_search.html index fcbe27e22..ca6939493 100644 --- a/ietf/templates/idtracker/idtracker_search.html +++ b/ietf/templates/idtracker/idtracker_search.html @@ -3,10 +3,10 @@ {% block title %}-- Search{% endblock %} {% block idcontent %} -

IESG Data Tracker

+
@@ -37,69 +37,30 @@ state: {{ form.cur_sub_state }} {{ form.area_acronym }} - - - - + + - - - +
I-D - Search Criteria
{{ form.note }}
+ +
+
+Document States: State Diagram and +State Explanations + +
+
{% if matches %} - {% regroup matches by draft.idstate as grouped %} - {% for group in grouped %} -

{{ group.grouper }}

- - - {% for match in group.list %} - - - - - - - - - {% endfor %} -
 Name (Intended Status)VerResponsible ADStatus DateModified
[VIEW]{{ match.draft.filename }} ({{ match.draft.intended_status }}){{ match.draft.revision }}{{ match.job_owner }}{{ match.status_date }}{{ match.event_date }}
- {% endfor %} +Search Result
+ {% regroup matches by docstate as grouped %} + {% include "idtracker/search_result_table.html" %} {% else %} -

No matches to your query.

-{% endif %} - -{% if debug %} -
-

Queries

-

- {{ sql_queries|length }} Queries - {% ifnotequal sql_queries|length 0 %} - (Show) - {% endifnotequal %} -

- - - - - - - - - - - - - {% for query in sql_queries %} - - - - {% endfor %} - - -
+ {% if searching %} +

No matches to your query.

+ {% endif %} {% endif %} {% endblock %} diff --git a/ietf/templates/idtracker/search_result_row.html b/ietf/templates/idtracker/search_result_row.html new file mode 100644 index 000000000..2643d3e1d --- /dev/null +++ b/ietf/templates/idtracker/search_result_row.html @@ -0,0 +1,13 @@ + + +
+ {# todo: conditionalize doclink properly #} + {% if match.primary_flag %}
  • {% else %}
    {% endif %}{{ match.document.filename }} ({{ match.document.intended_status }}) + {{ match.document.revision }} + {{ match.job_owner }} + {% firstof match.status_date "" %} + {{ match.event_date }} + diff --git a/ietf/templates/idtracker/search_result_table.html b/ietf/templates/idtracker/search_result_table.html new file mode 100644 index 000000000..591a32130 --- /dev/null +++ b/ietf/templates/idtracker/search_result_table.html @@ -0,0 +1,15 @@ + {% for group in grouped %} +

    {{ group.grouper }}

    + + + {% for match in group.list %} + {% include "idtracker/search_result_row.html" %} + {% if match.primary_flag %} + {% for match in match.ballot_others %} + {% include "idtracker/search_result_row.html" %} + {% endfor %} + {% endif %} + {% endfor %} +
     Name (Intended Status)VerResponsible ADStatus DateModified
    + {% endfor %} +