From b7bbfd83128cc1cef759a0b96de4a4791062493b Mon Sep 17 00:00:00 2001 From: Ryan Cross Date: Tue, 3 Nov 2015 07:52:05 +0000 Subject: [PATCH 1/5] Various small bug fixes and tweaks to UI of Liaison Management Tool. Commit ready for merge - Legacy-Id: 10382 --- ietf/liaisons/forms.py | 42 +++++++++++++++++---- ietf/liaisons/models.py | 44 ++++++++++++++++------ ietf/liaisons/tests.py | 1 + ietf/liaisons/utils.py | 14 ++++++- ietf/liaisons/views.py | 30 +++++++++++---- ietf/static/ietf/css/ietf.css | 4 ++ ietf/static/ietf/css/liaisons.css | 4 ++ ietf/static/ietf/js/liaisons.js | 6 +++ ietf/templates/liaisons/detail.html | 35 ++++++++++++----- ietf/templates/liaisons/liaison_base.html | 2 + ietf/templates/liaisons/liaison_mail.txt | 6 +-- ietf/templates/liaisons/liaison_table.html | 15 ++------ ietf/templates/liaisons/search_form.html | 2 +- 13 files changed, 149 insertions(+), 56 deletions(-) diff --git a/ietf/liaisons/forms.py b/ietf/liaisons/forms.py index f97a64c8a..2dcb4382b 100644 --- a/ietf/liaisons/forms.py +++ b/ietf/liaisons/forms.py @@ -46,6 +46,13 @@ with the IAB). def liaison_manager_sdos(person): return Group.objects.filter(type="sdo", state="active", role__person=person, role__name="liaiman").distinct() +def flatten_choices(choices): + '''Returns a flat choice list given one with option groups defined''' + flat = [] + for optgroup,options in choices: + flat.extend(options) + return flat + def get_internal_choices(user): '''Returns the set of internal IETF groups the user has permissions for, as a list of choices suitable for use in a select widget. If user == None, all active internal @@ -75,7 +82,8 @@ def get_groups_for_person(person): queries = [Q(role__person=person,role__name='chair',acronym='ietf'), Q(role__person=person,role__name__in=('chair','execdir'),acronym='iab'), Q(role__person=person,role__name='ad',type='area',state='active'), - Q(role__person=person,role__name__in=('chair','secretary'),type='wg',state='active')] + Q(role__person=person,role__name__in=('chair','secretary'),type='wg',state='active'), + Q(parent__role__person=person,parent__role__name='ad',type='wg',state='active')] return Group.objects.filter(reduce(operator.or_,queries)).order_by('acronym').distinct() def liaison_form_factory(request, type=None, **kwargs): @@ -126,15 +134,25 @@ class SearchLiaisonForm(forms.Form): start_date = DatepickerDateField(date_format="yyyy-mm-dd", picker_settings={"autoclose": "1" }, label='Start date', required=False) end_date = DatepickerDateField(date_format="yyyy-mm-dd", picker_settings={"autoclose": "1" }, label='End date', required=False) + def __init__(self, *args, **kwargs): + self.state = kwargs.pop('state') + super(SearchLiaisonForm, self).__init__(*args, **kwargs) + def get_results(self): - results = LiaisonStatement.objects.filter(state__slug='posted') + results = LiaisonStatement.objects.filter(state=self.state) if self.is_bound: query = self.cleaned_data.get('text') if query: - q = (Q(title__icontains=query) | Q(other_identifiers__icontains=query) | Q(body__icontains=query) | - Q(attachments__title__icontains=query,liaisonstatementattachment__removed=False) | - Q(technical_contacts__icontains=query) | Q(action_holder_contacts__icontains=query) | - Q(cc_contacts=query) | Q(response_contacts__icontains=query)) + q = (Q(title__icontains=query) | + Q(from_contact__address__icontains=query) | + Q(to_contacts__icontains=query) | + Q(other_identifiers__icontains=query) | + Q(body__icontains=query) | + Q(attachments__title__icontains=query,liaisonstatementattachment__removed=False) | + Q(technical_contacts__icontains=query) | + Q(action_holder_contacts__icontains=query) | + Q(cc_contacts=query) | + Q(response_contacts__icontains=query)) results = results.filter(q) source = self.cleaned_data.get('source') @@ -209,7 +227,8 @@ class LiaisonModelForm(BetterModelForm): self.fields["from_groups"].widget.attrs["placeholder"] = "Type in name to search for group" self.fields["to_groups"].widget.attrs["placeholder"] = "Type in name to search for group" self.fields["to_contacts"].label = 'Contacts' - + self.fields["other_identifiers"].widget.attrs["rows"] = 2 + # add email validators for field in ['from_contact','to_contacts','technical_contacts','action_holder_contacts','cc_contacts']: if field in self.fields: @@ -408,7 +427,14 @@ class OutgoingLiaisonForm(LiaisonModelForm): def set_from_fields(self): '''Set from_groups and from_contact options and initial value based on user accessing the form''' - self.fields['from_groups'].choices = get_internal_choices(self.user) + choices = get_internal_choices(self.user) + self.fields['from_groups'].choices = choices + + # set initial value if only one entry + flat_choices = flatten_choices(choices) + if len(flat_choices) == 1: + self.fields['from_groups'].initial = [flat_choices[0][0]] + if has_role(self.user, "Secretariat"): return diff --git a/ietf/liaisons/models.py b/ietf/liaisons/models.py index 648c5dda0..1744ebd84 100644 --- a/ietf/liaisons/models.py +++ b/ietf/liaisons/models.py @@ -24,11 +24,11 @@ STATE_EVENT_MAPPING = { class LiaisonStatement(models.Model): - title = models.CharField(blank=True, max_length=255) + title = models.CharField(max_length=255) from_groups = models.ManyToManyField(Group, blank=True, related_name='liaisonstatement_from_set') from_contact = models.ForeignKey(Email, blank=True, null=True) to_groups = models.ManyToManyField(Group, blank=True, related_name='liaisonstatement_to_set') - to_contacts = models.CharField(blank=True, max_length=255, help_text="Contacts at recipient body") + to_contacts = models.CharField(max_length=255, help_text="Contacts at recipient body") response_contacts = models.CharField(blank=True, max_length=255, help_text="Where to send a response") # RFC4053 technical_contacts = models.CharField(blank=True, max_length=255, help_text="Who to contact for clarification") # RFC4053 @@ -92,9 +92,12 @@ class LiaisonStatement(models.Model): @property def posted(self): - event = self.latest_event(type='posted') - if event: - return event.time + if hasattr(self,'prefetched_posted_events') and self.prefetched_posted_events: + return self.prefetched_posted_events[0].time + else: + event = self.latest_event(type='posted') + if event: + return event.time return None @property @@ -110,7 +113,7 @@ class LiaisonStatement(models.Model): for pending statements this is submitted date""" if self.state_id == 'posted': return self.posted - elif self.state_id == 'pending': + else: return self.submitted @property @@ -126,8 +129,11 @@ class LiaisonStatement(models.Model): @property def action_taken(self): - return self.tags.filter(slug='taken').exists() - + if hasattr(self,'prefetched_tags'): + return bool(self.prefetched_tags) + else: + return self.tags.filter(slug='taken').exists() + def active_attachments(self): '''Returns attachments with removed ones filtered out''' return self.attachments.exclude(liaisonstatementattachment__removed=True) @@ -138,17 +144,31 @@ class LiaisonStatement(models.Model): return bool(self._awaiting_action) return self.tags.filter(slug='awaiting').exists() + def _get_group_display(self, groups): + '''Returns comma separated string of group acronyms, non-wg are uppercase''' + acronyms = [] + for group in groups: + if group.type.slug == 'wg': + acronyms.append(group.acronym) + else: + acronyms.append(group.acronym.upper()) + return ', '.join(acronyms) + @property def from_groups_display(self): '''Returns comma separated list of from_group names''' - groups = self.from_groups.order_by('name').values_list('name',flat=True) - return ', '.join(groups) + if hasattr(self, 'prefetched_from_groups'): + return self._get_group_display(self.prefetched_from_groups) + else: + return self._get_group_display(self.from_groups.order_by('acronym')) @property def to_groups_display(self): '''Returns comma separated list of to_group names''' - groups = self.to_groups.order_by('name').values_list('name',flat=True) - return ', '.join(groups) + if hasattr(self, 'prefetched_to_groups'): + return self._get_group_display(self.prefetched_to_groups) + else: + return self._get_group_display(self.to_groups.order_by('acronym')) def from_groups_short_display(self): '''Returns comma separated list of from_group acronyms. For use in admin diff --git a/ietf/liaisons/tests.py b/ietf/liaisons/tests.py index 821cb3151..79f7f8a8e 100644 --- a/ietf/liaisons/tests.py +++ b/ietf/liaisons/tests.py @@ -889,6 +889,7 @@ class LiaisonManagementTests(TestCase): from_groups = ','.join([ str(x.pk) for x in liaison.from_groups.all() ]), from_contact = liaison.from_contact.address, to_groups = ','.join([ str(x.pk) for x in liaison.to_groups.all() ]), + to_contacts = 'to_contacts@example.com', purpose = liaison.purpose.slug, deadline = liaison.deadline, title = liaison.title, diff --git a/ietf/liaisons/utils.py b/ietf/liaisons/utils.py index 9e77a1e8d..d714a91c1 100644 --- a/ietf/liaisons/utils.py +++ b/ietf/liaisons/utils.py @@ -11,7 +11,7 @@ can_submit_liaison_required = passes_test_decorator( def approvable_liaison_statements(user): '''Returns a queryset of Liaison Statements in pending state that user has authority to approve''' - liaisons = LiaisonStatement.objects.filter(state__slug='pending') + liaisons = LiaisonStatement.objects.filter(state__slug__in=('pending','dead')) person = get_person_for_user(user) if has_role(user, "Secretariat"): return liaisons @@ -27,9 +27,19 @@ def approvable_liaison_statements(user): return liaisons.filter(id__in=approvable_liaisons) def can_edit_liaison(user, liaison): - '''Return True if user is Secretariat or Liaison Manager of all SDO groups involved''' + '''Returns True if user has edit / approval authority. + + True if: + - user is Secretariat + - liaison is outgoing and user has approval authority + - user is liaison manager of all SDOs involved + ''' if has_role(user, "Secretariat"): return True + + if liaison.is_outgoing() and liaison in approvable_liaison_statements(user): + return True + if has_role(user, "Liaison Manager"): person = get_person_for_user(user) for group in chain(liaison.from_groups.filter(type_id='sdo'),liaison.to_groups.filter(type_id='sdo')): diff --git a/ietf/liaisons/views.py b/ietf/liaisons/views.py index f39c4595b..d24dc0369 100644 --- a/ietf/liaisons/views.py +++ b/ietf/liaisons/views.py @@ -5,7 +5,7 @@ from email.utils import parseaddr from django.contrib import messages from django.core.urlresolvers import reverse as urlreverse from django.core.validators import validate_email, ValidationError -from django.db.models import Q +from django.db.models import Q, Prefetch from django.http import HttpResponse, HttpResponseForbidden from django.shortcuts import render, render_to_response, get_object_or_404, redirect from django.template import RequestContext @@ -21,6 +21,7 @@ from ietf.liaisons.utils import (get_person_for_user, can_add_outgoing_liaison, from ietf.liaisons.forms import liaison_form_factory, SearchLiaisonForm, EditAttachmentForm from ietf.liaisons.mails import notify_pending_by_email, send_liaison_by_email from ietf.liaisons.fields import select2_id_liaison_json +from ietf.name.models import LiaisonStatementTagName EMAIL_ALIASES = { 'IETFCHAIR':'The IETF Chair ', @@ -303,7 +304,10 @@ def liaison_add(request, type=None, **kwargs): liaison = form.save() # notifications - if 'send' in request.POST and liaison.state.slug == 'posted': + if 'save' in request.POST: + # the result of an edit, no notifications necessary + messages.success(request, 'The statement has been updated') + elif 'send' in request.POST and liaison.state.slug == 'posted': send_liaison_by_email(request, liaison) messages.success(request, 'The statement has been sent and posted') elif liaison.state.slug == 'pending': @@ -434,8 +438,14 @@ def liaison_edit_attachment(request, object_id, doc_id): def liaison_list(request, state='posted'): """A generic list view with tabs for different states: posted, pending, dead""" - liaisons = LiaisonStatement.objects.filter(state=state) - + # use prefetch to speed up main liaison page load + liaisons = LiaisonStatement.objects.filter(state=state).prefetch_related( + Prefetch('from_groups',queryset=Group.objects.order_by('acronym').select_related('type'),to_attr='prefetched_from_groups'), + Prefetch('to_groups',queryset=Group.objects.order_by('acronym').select_related('type'),to_attr='prefetched_to_groups'), + Prefetch('tags',queryset=LiaisonStatementTagName.objects.filter(slug='taken'),to_attr='prefetched_tags'), + Prefetch('liaisonstatementevent_set',queryset=LiaisonStatementEvent.objects.filter(type='posted'),to_attr='prefetched_posted_events') + ) + # check authorization for pending and dead tabs if state in ('pending','dead') and not can_add_liaison(request.user): msg = "Restricted to participants who are authorized to submit liaison statements on behalf of the various IETF entities" @@ -443,23 +453,26 @@ def liaison_list(request, state='posted'): # perform search / filter if 'text' in request.GET: - form = SearchLiaisonForm(data=request.GET) + form = SearchLiaisonForm(data=request.GET,state=state) search_conducted = True if form.is_valid(): results = form.get_results() liaisons = results else: - form = SearchLiaisonForm() + form = SearchLiaisonForm(state=state) search_conducted = False # perform sort sort, order_by = normalize_sort(request) if sort == 'date': liaisons = sorted(liaisons, key=lambda a: a.sort_date, reverse=True) + if sort == 'from_groups': - liaisons = sorted(liaisons, key=lambda a: a.from_groups_display) + liaisons = sorted(liaisons, key=lambda a: a.sort_date, reverse=True) + liaisons = sorted(liaisons, key=lambda a: a.from_groups_display.lower()) if sort == 'to_groups': - liaisons = sorted(liaisons, key=lambda a: a.to_groups_display) + liaisons = sorted(liaisons, key=lambda a: a.sort_date, reverse=True) + liaisons = sorted(liaisons, key=lambda a: a.to_groups_display.lower()) if sort == 'deadline': liaisons = liaisons.order_by('-deadline') if sort == 'title': @@ -501,6 +514,7 @@ def liaison_reply(request,object_id): initial = dict( to_groups=[ x.pk for x in liaison.from_groups.all() ], from_groups=[ x.pk for x in liaison.to_groups.all() ], + to_contacts=liaison.response_contacts, related_to=str(liaison.pk)) return liaison_add(request,type=reply_type,initial=initial) diff --git a/ietf/static/ietf/css/ietf.css b/ietf/static/ietf/css/ietf.css index 41831c26b..a1700fc63 100644 --- a/ietf/static/ietf/css/ietf.css +++ b/ietf/static/ietf/css/ietf.css @@ -320,6 +320,10 @@ ampersand you get is dependent on which fonts are available in the browser. Hac /* misc pages */ +.liaison-group-col { + min-width: 10em; +} + #reset-charter-milestones .date { display: inline-block; min-width: 5em; diff --git a/ietf/static/ietf/css/liaisons.css b/ietf/static/ietf/css/liaisons.css index 0a1586f90..02e34bb52 100644 --- a/ietf/static/ietf/css/liaisons.css +++ b/ietf/static/ietf/css/liaisons.css @@ -128,4 +128,8 @@ input[id$='DELETE'] { #id_to_groups + span { display: none; +} + +.liaison-group-col { + min-width: 10em; } \ No newline at end of file diff --git a/ietf/static/ietf/js/liaisons.js b/ietf/static/ietf/js/liaisons.js index 60b7c5c72..a55fe5e45 100644 --- a/ietf/static/ietf/js/liaisons.js +++ b/ietf/static/ietf/js/liaisons.js @@ -279,6 +279,7 @@ var searchForm = { init : function() { searchForm.form = $(this); searchForm.form.find(".search_field input,select").change(searchForm.toggleSubmit).click(searchForm.toggleSubmit).keyup(searchForm.toggleSubmit); + $("#search-clear-btn").bind("click", searchForm.clearForm); }, anyAdvancedActive : function() { @@ -298,6 +299,11 @@ var searchForm = { toggleSubmit : function() { var textSearch = $.trim($("#id_text").val()); searchForm.form.find("button[type=submit]").get(0).disabled = !textSearch && !searchForm.anyAdvancedActive(); + }, + + clearForm : function() { + var form = $(this).parents("form"); + form.find("input").val(""); } } diff --git a/ietf/templates/liaisons/detail.html b/ietf/templates/liaisons/detail.html index 594fab20f..0bcd2f5bf 100644 --- a/ietf/templates/liaisons/detail.html +++ b/ietf/templates/liaisons/detail.html @@ -21,12 +21,21 @@ {{ liaison.state }} - Submission Date - {{ liaison.submitted|date:"Y-m-d" }} + {% if liaison.state.slug == "posted" %} + Posted Date + {{ liaison.posted|date:"Y-m-d" }} + {% else %} + Submitted Date + {{ liaison.submitted|date:"Y-m-d" }} + {% endif %} + + From Group{{ liaison.from_groups.all|pluralize }} + {{ liaison.from_groups_display }} + {% if liaison.from_contact %} - Sender + From Contact {{ liaison.from_contact.person }} @@ -34,15 +43,19 @@ {% endif %} - From - {{ liaison.from_groups_display }} - - - - To + To Group{{ liaison.to_groups.all|pluralize }} {{ liaison.to_groups_display }} +{% if liaison.to_contacts %} + + To Contacts + + {{ liaison.to_contacts|parse_email_list|make_one_per_line|safe|linebreaksbr }} + + +{% endif %} + {% if liaison.cc_contacts %} Cc{{ liaison.cc_contacts|parse_email_list|make_one_per_line|safe|linebreaksbr }} @@ -177,7 +190,9 @@
{% csrf_token %} - {% if liaison.state.slug != 'dead' and can_edit %} + {% if liaison.state.slug == 'pending' and can_edit %} + Edit liaison + {% elif liaison.state.slug == 'posted' and user|has_role:"Secretariat" %} Edit liaison {% endif %} {% if liaison.state.slug != 'dead' and can_reply %} diff --git a/ietf/templates/liaisons/liaison_base.html b/ietf/templates/liaisons/liaison_base.html index b6a028e4e..02a4d875a 100644 --- a/ietf/templates/liaisons/liaison_base.html +++ b/ietf/templates/liaisons/liaison_base.html @@ -47,6 +47,8 @@ {% endblock group_content %} +

Total Statements: {{ liaisons|length }}

+ {% endblock content %} {% block js %} diff --git a/ietf/templates/liaisons/liaison_mail.txt b/ietf/templates/liaisons/liaison_mail.txt index 12f1c6283..8adcfad78 100644 --- a/ietf/templates/liaisons/liaison_mail.txt +++ b/ietf/templates/liaisons/liaison_mail.txt @@ -2,9 +2,9 @@ Submission Date: {{ liaison.submitted|date:"Y-m-d" }} URL of the IETF Web page: {{ liaison.get_absolute_url }} {% if liaison.deadline %}Please reply by {{ liaison.deadline }}{% endif %} -From: {{ liaison.from_name }} ({{ liaison.from_contact.person }} <{% if liaison.from_contact %}{{ liaison.from_contact.address }}{% endif %}>) -To: {{ liaison.to_name }} ({{ liaison.to_contacts }}) -Cc: {{ liaison.cc }} +From: {% if liaison.from_contact %}{{ liaison.from_contact.formatted_email }}{% endif %} +To: {{ liaison.to_contacts }} +Cc: {{ liaison.cc_contacts }} Response Contacts: {{ liaison.response_contacts }} Technical Contacts: {{ liaison.technical_contacts }} Purpose: {{ liaison.purpose.name }} diff --git a/ietf/templates/liaisons/liaison_table.html b/ietf/templates/liaisons/liaison_table.html index f1a9df3d3..0b45916ad 100644 --- a/ietf/templates/liaisons/liaison_table.html +++ b/ietf/templates/liaisons/liaison_table.html @@ -27,19 +27,10 @@ {% for liaison in liaisons %} {{ liaison.sort_date|date:"Y-m-d" }} - {{ liaison.from_groups_display }} - {{ liaison.to_groups_display }} + {{ liaison.from_groups_display }} + {{ liaison.to_groups_display }} {{ liaison.deadline|default:"-"|date:"Y-m-d" }}{% if liaison.deadline and not liaison.action_taken %}
Action Needed{% endif %} - - {% if not liaison.from_contact_id %} - {% for doc in liaison.attachments.all %} - {{ doc.title }} -
- {% endfor %} - {% else %} - {{ liaison.title }} - {% endif %} - + {{ liaison.title }} {% endfor %} diff --git a/ietf/templates/liaisons/search_form.html b/ietf/templates/liaisons/search_form.html index 65d368966..de76c26f6 100644 --- a/ietf/templates/liaisons/search_form.html +++ b/ietf/templates/liaisons/search_form.html @@ -70,7 +70,7 @@

- +
+ Back + {% endbuttons %} + +{% endblock %} diff --git a/ietf/templates/liaisons/detail_history.html b/ietf/templates/liaisons/detail_history.html index af73f9ecc..9749dc9b7 100644 --- a/ietf/templates/liaisons/detail_history.html +++ b/ietf/templates/liaisons/detail_history.html @@ -10,14 +10,11 @@ {% include "liaisons/detail_tabs.html" %} - {% comment %} {% if user|has_role:"Area Director,Secretariat,IANA,RFC Editor" %}

- Add comment - Add email + Add comment

{% endif %} - {% endcomment %} diff --git a/ietf/templates/liaisons/edit.html b/ietf/templates/liaisons/edit.html index 1dee7f659..a7a690f8c 100644 --- a/ietf/templates/liaisons/edit.html +++ b/ietf/templates/liaisons/edit.html @@ -43,7 +43,7 @@

Fields marked with are required. For detailed descriptions of the fields see the field help.

{% endif %} - {% csrf_token %} + {% csrf_token %} {% for fieldset in form.fieldsets %} {% if forloop.first and user|has_role:"Secretariat" %} diff --git a/ietf/templates/liaisons/liaison_table.html b/ietf/templates/liaisons/liaison_table.html index 0b45916ad..fecb0020d 100644 --- a/ietf/templates/liaisons/liaison_table.html +++ b/ietf/templates/liaisons/liaison_table.html @@ -29,7 +29,10 @@ - + {% endfor %} diff --git a/ietf/templates/liaisons/search_form.html b/ietf/templates/liaisons/search_form.html index de76c26f6..9fd569571 100644 --- a/ietf/templates/liaisons/search_form.html +++ b/ietf/templates/liaisons/search_form.html @@ -3,7 +3,7 @@ {% load ietf_filters %} {% load bootstrap3 %} - +
{{ form.text|add_class:"form-control"|attr:"placeholder:Title, body, identifiers, etc." }} @@ -32,7 +32,7 @@
- +
{{ form.source|add_class:"form-control" }} @@ -41,7 +41,7 @@
- +
{{ form.destination|add_class:"form-control" }} From eed28dbb491e8c8f45d1b3bb011314a75a3a747c Mon Sep 17 00:00:00 2001 From: Ryan Cross Date: Thu, 12 Nov 2015 18:44:28 +0000 Subject: [PATCH 5/5] Small fixes to Liaison Tool changes. Commit ready for merge - Legacy-Id: 10465 --- ietf/liaisons/feeds.py | 6 +++--- ietf/liaisons/migrations/0008_auto_20151110_1352.py | 2 +- ietf/name/fixtures/names.json | 10 ++++++++++ 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/ietf/liaisons/feeds.py b/ietf/liaisons/feeds.py index f9434d23b..cbe59f66b 100644 --- a/ietf/liaisons/feeds.py +++ b/ietf/liaisons/feeds.py @@ -41,11 +41,11 @@ class LiaisonStatementsFeed(Feed): # wildcards to make it easier to construct a URL that # matches search_string = re.sub(r"[^a-zA-Z1-9]", ".", search) - statement = LiaisonStatement.objects.filter(from_name__iregex=search_string).first() + statement = LiaisonStatement.objects.filter(from_groups__name__iregex=search_string).first() if not statement: raise FeedDoesNotExist - name = statement.from_name + name = statement.from_groups.first().name obj['filter'] = { 'from_name': name } obj['title'] = u'Liaison Statements from %s' % name return obj @@ -97,4 +97,4 @@ class LiaisonStatementsFeed(Feed): return item.submitted def item_author_name(self, item): - return item.from_name + return item.from_groups.first().name diff --git a/ietf/liaisons/migrations/0008_auto_20151110_1352.py b/ietf/liaisons/migrations/0008_auto_20151110_1352.py index 02090025f..605af9251 100644 --- a/ietf/liaisons/migrations/0008_auto_20151110_1352.py +++ b/ietf/liaisons/migrations/0008_auto_20151110_1352.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- from __future__ import unicode_literals -from django.db import models, migrations +from django.db import migrations def create_required_tags(apps, schema_editor): LiaisonStatement = apps.get_model("liaisons", "LiaisonStatement") diff --git a/ietf/name/fixtures/names.json b/ietf/name/fixtures/names.json index 8baaddb78..e270b992f 100644 --- a/ietf/name/fixtures/names.json +++ b/ietf/name/fixtures/names.json @@ -1580,6 +1580,16 @@ "model": "name.liaisonstatementeventtypename", "pk": "comment" }, +{ + "fields": { + "order": 10, + "used": true, + "name": "Private Comment", + "desc": "" + }, + "model": "name.liaisonstatementeventtypename", + "pk": "private_comment" +}, { "fields": { "order": 1,
{{ liaison.sort_date|date:"Y-m-d" }} {{ liaison.from_groups_display }} {{ liaison.to_groups_display }}{{ liaison.deadline|default:"-"|date:"Y-m-d" }}{% if liaison.deadline and not liaison.action_taken %}
Action Needed{% endif %}
{{ liaison.deadline|default:"-"|date:"Y-m-d" }} + {% if liaison.deadline and not liaison.action_taken %} +
Action Needed + {% endif %}
{{ liaison.title }}