Skip to content

Commit 5183042

Browse files
committed
Merged in branch/amsl/iprtool/5.7.4@8734 from rcross@amsl.com, providing new IPR models, refactored code, and improved list, search, and management interfaces.
- Legacy-Id: 8808
1 parent 04164ad commit 5183042

91 files changed

Lines changed: 6365 additions & 4231 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

ietf/doc/mails.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from django.core.urlresolvers import reverse as urlreverse
99

1010
from ietf.utils.mail import send_mail, send_mail_text
11-
from ietf.ipr.search import iprs_from_docs, related_docs
11+
from ietf.ipr.utils import iprs_from_docs, related_docs
1212
from ietf.doc.models import WriteupDocEvent, BallotPositionDocEvent, LastCallDocEvent, DocAlias, ConsensusDocEvent, DocTagName
1313
from ietf.doc.utils import needed_ballot_positions
1414
from ietf.person.models import Person
@@ -112,9 +112,9 @@ def generate_last_call_announcement(request, doc):
112112

113113
doc.filled_title = textwrap.fill(doc.title, width=70, subsequent_indent=" " * 3)
114114

115-
iprs, _ = iprs_from_docs(related_docs(DocAlias.objects.get(name=doc.canonical_name())))
115+
iprs = iprs_from_docs(related_docs(DocAlias.objects.get(name=doc.canonical_name())))
116116
if iprs:
117-
ipr_links = [ urlreverse("ietf.ipr.views.show", kwargs=dict(ipr_id=i.ipr_id)) for i in iprs]
117+
ipr_links = [ urlreverse("ietf.ipr.views.show", kwargs=dict(id=i.id)) for i in iprs]
118118
ipr_links = [ settings.IDTRACKER_BASE_URL+url if not url.startswith("http") else url for url in ipr_links ]
119119
else:
120120
ipr_links = None

ietf/doc/models.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -492,10 +492,10 @@ def friendly_state(self):
492492
else:
493493
return state.name
494494

495-
def ipr(self):
496-
"""Returns the IPR disclosures against this document (as a queryset over IprDocAlias)."""
497-
from ietf.ipr.models import IprDocAlias
498-
return IprDocAlias.objects.filter(doc_alias__document=self)
495+
def ipr(self,states=('posted','removed')):
496+
"""Returns the IPR disclosures against this document (as a queryset over IprDocRel)."""
497+
from ietf.ipr.models import IprDocRel
498+
return IprDocRel.objects.filter(document__document=self,disclosure__state__in=states)
499499

500500
def related_ipr(self):
501501
"""Returns the IPR disclosures against this document and those documents this

ietf/doc/templatetags/ietf_filters.py

Lines changed: 41 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,17 @@
99
from ietf.doc.models import ConsensusDocEvent
1010
from django import template
1111
from django.utils.html import escape, fix_ampersands
12+
from django.utils.text import wrap
1213
from django.template.defaultfilters import truncatewords_html, linebreaksbr, stringfilter, urlize
1314
from django.template import resolve_variable
1415
from django.utils.safestring import mark_safe, SafeData
1516
from django.utils.html import strip_tags
1617

1718
register = template.Library()
1819

20+
def collapsebr(html):
21+
return re.sub('(<(br ?/|/p)>[ \n]*)(<(br) ?/?>[ \n]*)*(<(br|p) ?/?>[ \n]*)', '\\1\\5', html)
22+
1923
@register.filter(name='expand_comma')
2024
def expand_comma(value):
2125
"""
@@ -280,7 +284,7 @@ def split(text, splitter=None):
280284
return text.split(splitter)
281285

282286
@register.filter(name="wrap_long_lines")
283-
def wrap_long_lines(text):
287+
def wrap_long_lines(text, width=72):
284288
"""Wraps long lines without loosing the formatting and indentation
285289
of short lines"""
286290
if not isinstance(text, (types.StringType,types.UnicodeType)):
@@ -441,26 +445,26 @@ def ad_area(user):
441445
return None
442446

443447
@register.filter
444-
def format_history_text(text):
448+
def format_history_text(text, trunc_words=25):
445449
"""Run history text through some cleaning and add ellipsis if it's too long."""
446450
full = mark_safe(text)
447451

448452
if text.startswith("This was part of a ballot set with:"):
449453
full = urlize_ietf_docs(full)
450454

451-
return format_snippet(full)
455+
return format_snippet(full, trunc_words)
452456

453457
@register.filter
454-
def format_snippet(text):
455-
full = mark_safe(keep_spacing(linebreaksbr(urlize(sanitize_html(text)))))
456-
snippet = truncatewords_html(full, 25)
458+
def format_snippet(text, trunc_words=25):
459+
full = mark_safe(keep_spacing(collapsebr(linebreaksbr(urlize(sanitize_html(text))))))
460+
snippet = truncatewords_html(full, trunc_words)
457461
if snippet != full:
458462
return mark_safe(u'<div class="snippet">%s<span class="show-all">[show all]</span></div><div style="display:none" class="full">%s</div>' % (snippet, full))
459463
return full
460464

461465
@register.filter
462466
def format_editable_snippet(text,link):
463-
full = mark_safe(keep_spacing(linebreaksbr(urlize(sanitize_html(text)))))
467+
full = mark_safe(keep_spacing(collapsebr(linebreaksbr(urlize(sanitize_html(text))))))
464468
snippet = truncatewords_html(full, 25)
465469
if snippet != full:
466470
return mark_safe(u'<div class="snippet">%s<span class="show-all">[show all]</span></div><div style="display:none" class="full">%s' % (format_editable(snippet,link),format_editable(full,link)) )
@@ -529,3 +533,33 @@ def consensus(doc):
529533
else:
530534
return "Unknown"
531535

536+
# The function and class below provides a tag version of the builtin wordwrap filter
537+
# https://djangosnippets.org/snippets/134/
538+
@register.tag
539+
def wordwrap(parser, token):
540+
"""
541+
This is a tag version of the Django builtin 'wordwrap' filter. This is useful
542+
if you need to wrap a combination of fixed template text and template variables.
543+
544+
Usage:
545+
546+
{% wordwrap 80 %}
547+
some really long text here, including template variable expansion, etc.
548+
{% endwordwrap %}
549+
"""
550+
try:
551+
tag_name, len = token.split_contents()
552+
except ValueError:
553+
raise template.TemplateSyntaxError, "The wordwrap tag requires exactly one argument: width."
554+
nodelist = parser.parse(('endwordwrap',))
555+
parser.delete_first_token()
556+
return WordWrapNode(nodelist, len)
557+
558+
class WordWrapNode(template.Node):
559+
def __init__(self, nodelist, len):
560+
self.nodelist = nodelist
561+
self.len = len
562+
563+
def render(self, context):
564+
return wrap(str(self.nodelist.render(context)), int(self.len))
565+

ietf/ipr/admin.py

Lines changed: 95 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,106 @@
11
#coding: utf-8
2+
from django import forms
23
from django.contrib import admin
3-
from ietf.ipr.models import IprContact, IprDetail, IprDocAlias, IprNotification, IprUpdate
4-
5-
class IprContactAdmin(admin.ModelAdmin):
6-
list_display=('__str__', 'ipr')
7-
admin.site.register(IprContact, IprContactAdmin)
8-
9-
class IprDetailAdmin(admin.ModelAdmin):
10-
list_display = ['title', 'submitted_date', 'docs', 'status']
4+
from ietf.name.models import DocRelationshipName
5+
from ietf.ipr.models import (IprNotification, IprDisclosureBase, IprDocRel, IprEvent,
6+
RelatedIpr, HolderIprDisclosure, ThirdPartyIprDisclosure, GenericIprDisclosure,
7+
NonDocSpecificIprDisclosure)
8+
9+
# ------------------------------------------------------
10+
# ModelAdmins
11+
# ------------------------------------------------------
12+
class IprDocRelAdminForm(forms.ModelForm):
13+
class Meta:
14+
model = IprDocRel
15+
widgets = {
16+
'sections':forms.TextInput,
17+
}
18+
19+
class IprDocRelInline(admin.TabularInline):
20+
model = IprDocRel
21+
form = IprDocRelAdminForm
22+
raw_id_fields = ['document']
23+
extra = 1
24+
25+
class RelatedIprInline(admin.TabularInline):
26+
model = RelatedIpr
27+
raw_id_fields = ['target']
28+
fk_name = 'source'
29+
extra = 1
30+
31+
def formfield_for_foreignkey(self, db_field, request, **kwargs):
32+
if db_field.name == "relationship":
33+
kwargs["queryset"] = DocRelationshipName.objects.filter(slug='updates')
34+
return super(RelatedIprInline, self).formfield_for_foreignkey(db_field, request, **kwargs)
35+
36+
class IprDisclosureBaseAdmin(admin.ModelAdmin):
37+
list_display = ['title', 'time', 'related_docs', 'state']
1138
search_fields = ['title', 'legal_name']
39+
raw_id_fields = ['by']
40+
inlines = [IprDocRelInline,RelatedIprInline]
41+
42+
def related_docs(self, obj):
43+
return u", ".join(a.formatted_name() for a in IprDocRel.objects.filter(disclosure=obj).order_by("id").select_related("document"))
44+
45+
admin.site.register(IprDisclosureBase, IprDisclosureBaseAdmin)
46+
47+
class HolderIprDisclosureAdmin(admin.ModelAdmin):
48+
list_display = ['title', 'time', 'related_docs', 'state']
49+
raw_id_fields = ["by"]
50+
inlines = [IprDocRelInline,RelatedIprInline]
51+
52+
def related_docs(self, obj):
53+
return u", ".join(a.formatted_name() for a in IprDocRel.objects.filter(disclosure=obj).order_by("id").select_related("document"))
54+
55+
admin.site.register(HolderIprDisclosure, HolderIprDisclosureAdmin)
1256

13-
def docs(self, ipr):
14-
return u", ".join(a.formatted_name() for a in IprDocAlias.objects.filter(ipr=ipr).order_by("id").select_related("doc_alias"))
57+
class ThirdPartyIprDisclosureAdmin(admin.ModelAdmin):
58+
list_display = ['title', 'time', 'related_docs', 'state']
59+
raw_id_fields = ["by"]
60+
inlines = [IprDocRelInline,RelatedIprInline]
61+
62+
def related_docs(self, obj):
63+
return u", ".join(a.formatted_name() for a in IprDocRel.objects.filter(disclosure=obj).order_by("id").select_related("document"))
1564

16-
admin.site.register(IprDetail, IprDetailAdmin)
65+
admin.site.register(ThirdPartyIprDisclosure, ThirdPartyIprDisclosureAdmin)
66+
67+
class GenericIprDisclosureAdmin(admin.ModelAdmin):
68+
list_display = ['title', 'time', 'related_docs', 'state']
69+
raw_id_fields = ["by"]
70+
inlines = [RelatedIprInline]
71+
72+
def related_docs(self, obj):
73+
return u", ".join(a.formatted_name() for a in IprDocRel.objects.filter(disclosure=obj).order_by("id").select_related("document"))
74+
75+
admin.site.register(GenericIprDisclosure, GenericIprDisclosureAdmin)
76+
77+
class NonDocSpecificIprDisclosureAdmin(admin.ModelAdmin):
78+
list_display = ['title', 'time', 'related_docs', 'state']
79+
raw_id_fields = ["by"]
80+
inlines = [RelatedIprInline]
81+
82+
def related_docs(self, obj):
83+
return u", ".join(a.formatted_name() for a in IprDocRel.objects.filter(disclosure=obj).order_by("id").select_related("document"))
84+
85+
admin.site.register(NonDocSpecificIprDisclosure, NonDocSpecificIprDisclosureAdmin)
1786

1887
class IprNotificationAdmin(admin.ModelAdmin):
1988
pass
2089
admin.site.register(IprNotification, IprNotificationAdmin)
2190

22-
class IprUpdateAdmin(admin.ModelAdmin):
23-
pass
24-
admin.site.register(IprUpdate, IprUpdateAdmin)
91+
class IprDocRelAdmin(admin.ModelAdmin):
92+
raw_id_fields = ["disclosure", "document"]
93+
admin.site.register(IprDocRel, IprDocRelAdmin)
94+
95+
class RelatedIprAdmin(admin.ModelAdmin):
96+
list_display = ['source', 'target', 'relationship', ]
97+
search_fields = ['source__name', 'target__name', 'target__document__name', ]
98+
raw_id_fields = ['source', 'target', ]
99+
admin.site.register(RelatedIpr, RelatedIprAdmin)
25100

26-
class IprDocAliasAdmin(admin.ModelAdmin):
27-
raw_id_fields = ["ipr", "doc_alias"]
28-
admin.site.register(IprDocAlias, IprDocAliasAdmin)
101+
class IprEventAdmin(admin.ModelAdmin):
102+
list_display = ["disclosure", "type", "by", "time"]
103+
list_filter = ["time", "type"]
104+
search_fields = ["disclosure__title", "by__name"]
105+
raw_id_fields = ["disclosure", "by", "message", "in_reply_to"]
106+
admin.site.register(IprEvent, IprEventAdmin)

ietf/ipr/feeds.py

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
# Copyright The IETF Trust 2007, All Rights Reserved
22

3-
import datetime
4-
53
from django.contrib.syndication.views import Feed
64
from django.utils.feedgenerator import Atom1Feed
75
from django.core.urlresolvers import reverse_lazy
86
from django.utils.safestring import mark_safe
97

10-
from ietf.ipr.models import IprDetail
8+
from ietf.ipr.models import IprDisclosureBase
119

1210
class LatestIprDisclosuresFeed(Feed):
1311
feed_type = Atom1Feed
@@ -18,7 +16,7 @@ class LatestIprDisclosuresFeed(Feed):
1816
feed_url = "/feed/ipr/"
1917

2018
def items(self):
21-
return IprDetail.objects.filter(status__in=[1,3]).order_by('-submitted_date')[:30]
19+
return IprDisclosureBase.objects.filter(state__in=('posted','removed')).order_by('-time')[:30]
2220

2321
def item_title(self, item):
2422
return mark_safe(item.title)
@@ -27,18 +25,16 @@ def item_description(self, item):
2725
return unicode(item.title)
2826

2927
def item_pubdate(self, item):
30-
# this method needs to return a datetime instance, even
31-
# though the database has only date, not time
32-
return datetime.datetime.combine(item.submitted_date, datetime.time(0,0,0))
28+
return item.time
3329

3430
def item_author_name(self, item):
35-
s = item.get_submitter()
36-
if s:
37-
return s.name
38-
return None
31+
if item.by:
32+
return item.by.name
33+
else:
34+
return None
3935

4036
def item_author_email(self, item):
41-
s = item.get_submitter()
42-
if s:
43-
return s.email
44-
return None
37+
if item.by:
38+
return item.by.email_address()
39+
else:
40+
return None

0 commit comments

Comments
 (0)