Merged in ^/personal/henrik/6.68.4-ipr@14609 from henrik@levkowetz.com:
Changes to the IPR disclosure pages, requested during WG Chairs Lunch where the changes to IPR handling introduced by RFC8179 were presented. - Legacy-Id: 14610
This commit is contained in:
commit
a4cc4bba2e
27
changelog
27
changelog
|
@ -1,3 +1,30 @@
|
|||
ietfdb (6.72.0) ietf; urgency=medium
|
||||
|
||||
**Updated IPR disclosure pages**
|
||||
|
||||
This release introduces changes to the IPR disclosure pages, requested
|
||||
during WG Chairs Lunch where the changes to IPR handling introduced by
|
||||
RFC8179 were presented. From the commit log:
|
||||
|
||||
* Changed the IPR disclosure page for IPR disclosure updates to show both
|
||||
the previous and current disclosure details side-by-side. Fixes issue
|
||||
#2414.
|
||||
|
||||
* Rewrote text_to_dict() and dict_to_text() to support unicode without
|
||||
RFC2822 encoding issues. Added initial values in IPR update forms, from
|
||||
the original disclosure, in order to make updates easier. Addresses issue
|
||||
#2413.
|
||||
|
||||
* Added a new section for IPR disclosures on related documents to the IPR
|
||||
document search result page. Fixes issue #2412.
|
||||
|
||||
* Changed the patent information text fields to individual fields for
|
||||
patent number, inventor, title, date and notes, with validation. Fixes
|
||||
issue #2411.
|
||||
|
||||
-- Henrik Levkowetz <henrik@levkowetz.com> 01 Feb 2018 07:10:21 -0800
|
||||
|
||||
|
||||
ietfdb (6.71.1) ietf; urgency=low
|
||||
|
||||
This is a small bugfix release related to the new non-wg mailing list index
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
import datetime
|
||||
import email
|
||||
|
||||
from django.utils.safestring import mark_safe
|
||||
|
||||
from django import forms
|
||||
from django.core.validators import RegexValidator
|
||||
from django.utils.safestring import mark_safe
|
||||
|
||||
import debug # pyflakes:ignore
|
||||
|
||||
from ietf.group.models import Group
|
||||
from ietf.doc.fields import SearchableDocAliasField
|
||||
|
@ -13,6 +17,7 @@ from ietf.ipr.models import (IprDocRel, IprDisclosureBase, HolderIprDisclosure,
|
|||
IprLicenseTypeName, IprDisclosureStateName)
|
||||
from ietf.message.models import Message
|
||||
from ietf.utils.fields import DatepickerDateField
|
||||
from ietf.utils.text import dict_to_text
|
||||
|
||||
# ----------------------------------------------------------------
|
||||
# Globals
|
||||
|
@ -101,6 +106,31 @@ class DraftForm(forms.ModelForm):
|
|||
}
|
||||
help_texts = { 'sections': 'Sections' }
|
||||
|
||||
validate_patent_number = RegexValidator(
|
||||
regex="^(([A-Z][A-Z]\d{6,12}|[A-Z][A-Z]\d{4}(\w{1,2}\d{5,7})?)[, ]*)+$",
|
||||
message="Please enter one or more patent publication or application numbers as country code and serial number, e.g.: WO2017123456." )
|
||||
|
||||
def validate_string(s, letter_min, digit_min, space_min, message):
|
||||
letter_count = 0
|
||||
space_count = 0
|
||||
digit_count = 0
|
||||
s = s.strip()
|
||||
for c in s:
|
||||
if c.isalpha():
|
||||
letter_count += 1
|
||||
if c.isspace():
|
||||
space_count += 1
|
||||
if not (letter_count >= letter_min and digit_count >= digit_min and space_count >= space_min):
|
||||
raise forms.ValidationError(message)
|
||||
|
||||
def validate_name(name):
|
||||
return validate_string(name, letter_min=3, space_min=1, digit_min=0,
|
||||
message="This doesn't look like a name. Please enter the actual inventor name.")
|
||||
|
||||
def validate_title(title):
|
||||
return validate_string(title, letter_min=15, space_min=2, digit_min=0,
|
||||
message="This doesn't look like a patent title. Please enter the actual patent title.")
|
||||
|
||||
class GenericDisclosureForm(forms.Form):
|
||||
"""Custom ModelForm-like form to use for new Generic or NonDocSpecific Iprs.
|
||||
If patent_info is submitted create a NonDocSpecificIprDisclosure object
|
||||
|
@ -114,7 +144,14 @@ class GenericDisclosureForm(forms.Form):
|
|||
holder_contact_info = forms.CharField(label="Other Info (address, phone, etc.)", max_length=255,widget=forms.Textarea,required=False, strip=False)
|
||||
submitter_name = forms.CharField(max_length=255,required=False)
|
||||
submitter_email = forms.EmailField(required=False)
|
||||
patent_info = forms.CharField(max_length=255,widget=forms.Textarea, required=False, help_text="Patent, Serial, Publication, Registration, or Application/File number(s), Date(s) granted or applied for, Country, and any additional notes.", strip=False)
|
||||
#patent_info = forms.CharField(max_length=255,widget=forms.Textarea, required=False, help_text="Patent, Serial, Publication, Registration, or Application/File number(s), Date(s) granted or applied for, Country, and any additional notes.", strip=False)
|
||||
patent_number = forms.CharField(max_length=127, required=False, validators=[ validate_patent_number ],
|
||||
help_text = "Patent publication or application number (2-letter country code followed by serial number)")
|
||||
patent_inventor = forms.CharField(max_length=63, required=False, validators=[ validate_name ], help_text="Inventor name")
|
||||
patent_title = forms.CharField(max_length=63, required=False, validators=[ validate_title ], help_text="Title of invention")
|
||||
patent_date = forms.DateField(required=False, help_text="Date granted or applied for")
|
||||
patent_notes = forms.CharField(max_length=127, required=False, widget=forms.Textarea)
|
||||
|
||||
has_patent_pending = forms.BooleanField(required=False)
|
||||
statement = forms.CharField(max_length=255,widget=forms.Textarea,required=False, strip=False)
|
||||
updates = SearchableIprDisclosuresField(required=False, help_text="If this disclosure <strong>updates</strong> other disclosures identify here which ones. Leave this field blank if this disclosure does not update any prior disclosures. <strong>Note</strong>: Updates to IPR disclosures must only be made by authorized representatives of the original submitters. Updates will automatically be forwarded to the current Patent Holder's Contact and to the Submitter of the original IPR disclosure.")
|
||||
|
@ -132,7 +169,21 @@ class GenericDisclosureForm(forms.Form):
|
|||
if not self.cleaned_data.get('same_as_ii_above'):
|
||||
if not ( self.cleaned_data.get('submitter_name') and self.cleaned_data.get('submitter_email') ):
|
||||
raise forms.ValidationError('Submitter information must be provided in section VII')
|
||||
|
||||
|
||||
patent_fields = [ 'patent_'+k for k in ['number', 'inventor', 'title', 'date', ] ]
|
||||
patent_values = [ cleaned_data.get(k) for k in patent_fields ]
|
||||
if any(patent_values) and not all(patent_values):
|
||||
for k in patent_fields:
|
||||
if not cleaned_data.get(k):
|
||||
self.add_error(k, "This field is required if you are filing a patent-specific disclosure.")
|
||||
raise forms.ValidationError("A generic IPR disclosure cannot have any patent-specific information, "
|
||||
"but a patent-specific disclosure must provide full patent information.")
|
||||
|
||||
patent_fields += ['patent_notes']
|
||||
patent_info = dict([ (k.replace('patent_','').capitalize(), cleaned_data.get(k)) for k in patent_fields if cleaned_data.get(k) ] )
|
||||
cleaned_data['patent_info'] = dict_to_text(patent_info).strip()
|
||||
cleaned_data['patent_fields'] = patent_fields
|
||||
|
||||
return cleaned_data
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
|
@ -140,6 +191,9 @@ class GenericDisclosureForm(forms.Form):
|
|||
same_as_ii_above = nargs.get('same_as_ii_above')
|
||||
del nargs['same_as_ii_above']
|
||||
|
||||
for k in self.cleaned_data['patent_fields'] + ['patent_fields',]:
|
||||
del nargs[k]
|
||||
|
||||
if self.cleaned_data.get('patent_info'):
|
||||
obj = NonDocSpecificIprDisclosure(**nargs)
|
||||
else:
|
||||
|
@ -160,6 +214,12 @@ class IprDisclosureFormBase(forms.ModelForm):
|
|||
"""Base form for Holder and ThirdParty disclosures"""
|
||||
updates = SearchableIprDisclosuresField(required=False, help_text=mark_safe("If this disclosure <strong>updates</strong> other disclosures identify here which ones. Leave this field blank if this disclosure does not update any prior disclosures. Note: Updates to IPR disclosures must only be made by authorized representatives of the original submitters. Updates will automatically be forwarded to the current Patent Holder's Contact and to the Submitter of the original IPR disclosure."))
|
||||
same_as_ii_above = forms.BooleanField(required=False)
|
||||
patent_number = forms.CharField(max_length=127, required=True, validators=[ validate_patent_number ],
|
||||
help_text = "Patent publication or application number (2-letter country code followed by serial number)")
|
||||
patent_inventor = forms.CharField(max_length=63, required=True, validators=[ validate_name ], help_text="Inventor name")
|
||||
patent_title = forms.CharField(max_length=63, required=True, validators=[ validate_title ], help_text="Title of invention")
|
||||
patent_date = forms.DateField(required=True, help_text="Date granted or applied for")
|
||||
patent_notes = forms.CharField(max_length=127, required=False, widget=forms.Textarea)
|
||||
|
||||
def __init__(self,*args,**kwargs):
|
||||
super(IprDisclosureFormBase, self).__init__(*args,**kwargs)
|
||||
|
@ -167,6 +227,7 @@ class IprDisclosureFormBase(forms.ModelForm):
|
|||
self.fields['submitter_email'].required = False
|
||||
self.fields['compliant'].initial = True
|
||||
self.fields['compliant'].label = "This disclosure complies with RFC 3979"
|
||||
patent_fields = [ 'patent_'+k for k in ['number', 'inventor', 'title', 'date', ] ]
|
||||
if "ietfer_name" in self.fields:
|
||||
self.fields["ietfer_name"].label = "Name"
|
||||
if "ietfer_contact_email" in self.fields:
|
||||
|
@ -175,7 +236,10 @@ class IprDisclosureFormBase(forms.ModelForm):
|
|||
self.fields["ietfer_contact_info"].label = "Other info"
|
||||
self.fields["ietfer_contact_info"].help_text = "Address, phone, etc."
|
||||
if "patent_info" in self.fields:
|
||||
self.fields["patent_info"].help_text = "Patent, Serial, Publication, Registration, or Application/File number(s), Date(s) granted or applied for, Country, and any additional notes"
|
||||
self.fields['patent_info'].required = False
|
||||
else:
|
||||
for f in patent_fields:
|
||||
del self.fields[f]
|
||||
if "licensing" in self.fields:
|
||||
self.fields["licensing_comments"].label = "Licensing information, comments, notes, or URL for further information"
|
||||
if "submitter_claims_all_terms_disclosed" in self.fields:
|
||||
|
@ -187,7 +251,7 @@ class IprDisclosureFormBase(forms.ModelForm):
|
|||
"""This will be overridden"""
|
||||
model = IprDisclosureBase
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
def clean(self):
|
||||
super(IprDisclosureFormBase, self).clean()
|
||||
cleaned_data = self.cleaned_data
|
||||
|
@ -198,6 +262,12 @@ class IprDisclosureFormBase(forms.ModelForm):
|
|||
if not ( self.cleaned_data.get('submitter_name') and self.cleaned_data.get('submitter_email') ):
|
||||
raise forms.ValidationError('Submitter information must be provided in section VII')
|
||||
|
||||
patent_fields = [ 'patent_'+k for k in ['number', 'inventor', 'title', 'date', 'notes'] ]
|
||||
|
||||
patent_info = dict([ (k.replace('patent_','').capitalize(), cleaned_data.get(k)) for k in patent_fields if cleaned_data.get(k) ] )
|
||||
cleaned_data['patent_info'] = dict_to_text(patent_info).strip()
|
||||
cleaned_data['patent_fields'] = patent_fields
|
||||
|
||||
return cleaned_data
|
||||
|
||||
class HolderIprDisclosureForm(IprDisclosureFormBase):
|
||||
|
@ -220,8 +290,7 @@ class HolderIprDisclosureForm(IprDisclosureFormBase):
|
|||
self.fields['licensing'].queryset = IprLicenseTypeName.objects.exclude(slug='none-selected')
|
||||
|
||||
def clean(self):
|
||||
super(HolderIprDisclosureForm, self).clean()
|
||||
cleaned_data = self.cleaned_data
|
||||
cleaned_data = super(HolderIprDisclosureForm, self).clean()
|
||||
if not self.data.get('iprdocrel_set-0-document') and not cleaned_data.get('other_designations'):
|
||||
raise forms.ValidationError('You need to specify a contribution in Section IV')
|
||||
return cleaned_data
|
||||
|
@ -270,8 +339,7 @@ class ThirdPartyIprDisclosureForm(IprDisclosureFormBase):
|
|||
exclude = [ 'by','docs','state','rel' ]
|
||||
|
||||
def clean(self):
|
||||
super(ThirdPartyIprDisclosureForm, self).clean()
|
||||
cleaned_data = self.cleaned_data
|
||||
cleaned_data = super(ThirdPartyIprDisclosureForm, self).clean()
|
||||
if not self.data.get('iprdocrel_set-0-document') and not cleaned_data.get('other_designations'):
|
||||
raise forms.ValidationError('You need to specify a contribution in Section III')
|
||||
return cleaned_data
|
||||
|
|
|
@ -39,7 +39,7 @@ class IprTests(TestCase):
|
|||
title="Statement regarding rights Update",
|
||||
holder_legal_name="Native Martians United",
|
||||
state_id='pending',
|
||||
patent_info='US12345',
|
||||
patent_info='Number: US12345\nTitle: A method of transfering bits\nInventor: A. Nonymous\nDate: 2000-01-01',
|
||||
holder_contact_name='Update Holder',
|
||||
holder_contact_email='update_holder@acme.com',
|
||||
licensing_id='royalty-free',
|
||||
|
@ -292,7 +292,7 @@ class IprTests(TestCase):
|
|||
ipr = iprs[0]
|
||||
self.assertEqual(ipr.holder_legal_name, "Test Legal")
|
||||
self.assertEqual(ipr.state.slug, 'pending')
|
||||
self.assertTrue(isinstance(ipr.get_child(),GenericIprDisclosure))
|
||||
self.assertTrue(isinstance(ipr.get_child(), GenericIprDisclosure))
|
||||
|
||||
def test_new_specific(self):
|
||||
"""Add a new specific disclosure. Note: submitter does not need to be logged in.
|
||||
|
@ -314,14 +314,16 @@ class IprTests(TestCase):
|
|||
"iprdocrel_set-0-document": "%s" % draft.docalias_set.first().pk,
|
||||
"iprdocrel_set-0-revisions": '00',
|
||||
"iprdocrel_set-1-document": DocAlias.objects.filter(name__startswith="rfc").first().pk,
|
||||
"patent_info": "none",
|
||||
"patent_number": "SE12345678901",
|
||||
"patent_inventor": "A. Nonymous",
|
||||
"patent_title": "A method of transfering bits",
|
||||
"patent_date": "2000-01-01",
|
||||
"has_patent_pending": False,
|
||||
"licensing": "royalty-free",
|
||||
"submitter_name": "Test Holder",
|
||||
"submitter_email": "test@holder.com",
|
||||
})
|
||||
self.assertEqual(r.status_code, 200)
|
||||
# print r.content
|
||||
self.assertTrue("Your IPR disclosure has been submitted" in unicontent(r))
|
||||
|
||||
iprs = IprDisclosureBase.objects.filter(title__icontains=draft.name)
|
||||
|
@ -329,6 +331,8 @@ class IprTests(TestCase):
|
|||
ipr = iprs[0]
|
||||
self.assertEqual(ipr.holder_legal_name, "Test Legal")
|
||||
self.assertEqual(ipr.state.slug, 'pending')
|
||||
for item in [u'SE12345678901','A method of transfering bits','2000-01-01']:
|
||||
self.assertIn(item, ipr.get_child().patent_info)
|
||||
self.assertTrue(isinstance(ipr.get_child(),HolderIprDisclosure))
|
||||
self.assertEqual(len(outbox),1)
|
||||
self.assertTrue('New IPR Submission' in outbox[0]['Subject'])
|
||||
|
@ -352,7 +356,10 @@ class IprTests(TestCase):
|
|||
"iprdocrel_set-0-document": "%s" % draft.docalias_set.first().pk,
|
||||
"iprdocrel_set-0-revisions": '00',
|
||||
"iprdocrel_set-1-document": DocAlias.objects.filter(name__startswith="rfc").first().pk,
|
||||
"patent_info": "none",
|
||||
"patent_number": "SE12345678901",
|
||||
"patent_inventor": "A. Nonymous",
|
||||
"patent_title": "A method of transfering bits",
|
||||
"patent_date": "2000-01-01",
|
||||
"has_patent_pending": False,
|
||||
"licensing": "royalty-free",
|
||||
"submitter_name": "Test Holder",
|
||||
|
@ -366,6 +373,8 @@ class IprTests(TestCase):
|
|||
ipr = iprs[0]
|
||||
self.assertEqual(ipr.holder_legal_name, "Test Legal")
|
||||
self.assertEqual(ipr.state.slug, "pending")
|
||||
for item in [u'SE12345678901','A method of transfering bits','2000-01-01' ]:
|
||||
self.assertIn(item, ipr.get_child().patent_info)
|
||||
self.assertTrue(isinstance(ipr.get_child(),ThirdPartyIprDisclosure))
|
||||
self.assertEqual(len(outbox),1)
|
||||
self.assertTrue('New IPR Submission' in outbox[0]['Subject'])
|
||||
|
@ -374,8 +383,13 @@ class IprTests(TestCase):
|
|||
def test_update(self):
|
||||
draft = make_test_data()
|
||||
original_ipr = IprDisclosureBase.objects.get(title='Statement regarding rights')
|
||||
url = urlreverse("ietf.ipr.views.new", kwargs={ "type": "specific" })
|
||||
|
||||
# get
|
||||
url = urlreverse("ietf.ipr.views.update", kwargs={ "id": original_ipr.id })
|
||||
r = self.client.get(url)
|
||||
self.assertContains(r, "Statement regarding rights")
|
||||
|
||||
#url = urlreverse("ietf.ipr.views.new", kwargs={ "type": "specific" })
|
||||
# successful post
|
||||
empty_outbox()
|
||||
r = self.client.post(url, {
|
||||
|
@ -391,7 +405,10 @@ class IprTests(TestCase):
|
|||
"iprdocrel_set-0-document": "%s" % draft.docalias_set.first().pk,
|
||||
"iprdocrel_set-0-revisions": '00',
|
||||
"iprdocrel_set-1-document": DocAlias.objects.filter(name__startswith="rfc").first().pk,
|
||||
"patent_info": "none",
|
||||
"patent_number": "SE12345678901",
|
||||
"patent_inventor": "A. Nonymous",
|
||||
"patent_title": "A method of transfering bits",
|
||||
"patent_date": "2000-01-01",
|
||||
"has_patent_pending": False,
|
||||
"licensing": "royalty-free",
|
||||
"submitter_name": "Test Holder",
|
||||
|
@ -415,7 +432,6 @@ class IprTests(TestCase):
|
|||
draft = make_test_data()
|
||||
url = urlreverse("ietf.ipr.views.new", kwargs={ "type": "specific" })
|
||||
|
||||
# successful post
|
||||
empty_outbox()
|
||||
r = self.client.post(url, {
|
||||
"updates": "this is supposed to be an integer",
|
||||
|
@ -426,7 +442,10 @@ class IprTests(TestCase):
|
|||
"iprdocrel_set-INITIAL_FORMS": 0,
|
||||
"iprdocrel_set-0-document": "%s" % draft.docalias_set.first().pk,
|
||||
"iprdocrel_set-0-revisions": '00',
|
||||
"patent_info": "none",
|
||||
"patent_number": "SE12345678901",
|
||||
"patent_inventor": "A. Nonymous",
|
||||
"patent_title": "A method of transfering bits",
|
||||
"patent_date": "2000-01-01",
|
||||
"has_patent_pending": False,
|
||||
"licensing": "royalty-free",
|
||||
"submitter_name": "Test Holder",
|
||||
|
|
|
@ -29,11 +29,11 @@ def iprs_from_docs(aliases,**kwargs):
|
|||
iprdocrels += alias.document.ipr(**kwargs)
|
||||
return list(set([i.disclosure for i in iprdocrels]))
|
||||
|
||||
def related_docs(alias):
|
||||
def related_docs(alias, relationship=['replaces', 'obs']):
|
||||
"""Returns list of related documents"""
|
||||
results = list(alias.document.docalias_set.all())
|
||||
|
||||
rels = alias.document.all_relations_that_doc(['replaces','obs'])
|
||||
rels = alias.document.all_relations_that_doc(relationship)
|
||||
|
||||
for rel in rels:
|
||||
rel_aliases = list(rel.target.document.docalias_set.all())
|
||||
|
@ -42,4 +42,6 @@ def related_docs(alias):
|
|||
x.related = rel
|
||||
x.relation = rel.relationship.revname
|
||||
results += rel_aliases
|
||||
return list(set(results))
|
||||
return list(set(results))
|
||||
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ from django.conf import settings
|
|||
from django.contrib import messages
|
||||
from django.urls import reverse as urlreverse
|
||||
from django.db.models import Q
|
||||
from django.forms.models import inlineformset_factory
|
||||
from django.forms.models import inlineformset_factory, model_to_dict
|
||||
from django.forms.formsets import formset_factory
|
||||
from django.http import HttpResponse, Http404, HttpResponseRedirect
|
||||
from django.shortcuts import render, get_object_or_404, redirect
|
||||
|
@ -30,6 +30,7 @@ from ietf.ipr.models import (IprDisclosureStateName, IprDisclosureBase,
|
|||
RelatedIpr,IprEvent)
|
||||
from ietf.ipr.utils import (get_genitive, get_ipr_summary,
|
||||
iprs_from_docs, related_docs)
|
||||
from ietf.mailtrigger.utils import gather_address_lists
|
||||
from ietf.message.models import Message
|
||||
from ietf.message.utils import infer_message
|
||||
from ietf.name.models import IprLicenseTypeName
|
||||
|
@ -37,7 +38,7 @@ from ietf.person.models import Person
|
|||
from ietf.secr.utils.document import get_rfc_num, is_draft
|
||||
from ietf.utils.draft_search import normalize_draftname
|
||||
from ietf.utils.mail import send_mail, send_mail_message
|
||||
from ietf.mailtrigger.utils import gather_address_lists
|
||||
from ietf.utils.text import text_to_dict
|
||||
|
||||
# ----------------------------------------------------------------
|
||||
# Globals
|
||||
|
@ -531,7 +532,16 @@ def new(request, type, updates=None):
|
|||
|
||||
else:
|
||||
if updates:
|
||||
form = ipr_form_mapping[type](initial={'updates':str(updates)})
|
||||
original = IprDisclosureBase(id=updates).get_child()
|
||||
initial = model_to_dict(original)
|
||||
initial.update({'updates':str(updates), })
|
||||
patent_info = text_to_dict(initial['patent_info'])
|
||||
if patent_info.keys():
|
||||
patent_dict = dict([ ('patent_'+k.lower(), v) for k,v in patent_info.items() ])
|
||||
else:
|
||||
patent_dict = {'patent_notes': initial['patent_info']}
|
||||
initial.update(patent_dict)
|
||||
form = ipr_form_mapping[type](initial=initial)
|
||||
else:
|
||||
form = ipr_form_mapping[type]()
|
||||
disclosure = IprDisclosureBase() # dummy disclosure for inlineformset
|
||||
|
@ -619,7 +629,8 @@ def search(request):
|
|||
docid = request.GET.get("id") or request.GET.get("id_document_tag") or ""
|
||||
docs = doc = None
|
||||
iprs = []
|
||||
|
||||
related_iprs = []
|
||||
|
||||
# set states
|
||||
states = request.GET.getlist('state',('posted','removed'))
|
||||
if states == ['all']:
|
||||
|
@ -647,10 +658,12 @@ def search(request):
|
|||
# one match
|
||||
if len(start) == 1:
|
||||
first = start[0]
|
||||
doc = str(first)
|
||||
doc = first.document
|
||||
docs = related_docs(first)
|
||||
iprs = iprs_from_docs(docs,states=states)
|
||||
template = "ipr/search_doc_result.html"
|
||||
updated_docs = related_docs(first, ['updates',])
|
||||
related_iprs = list(set(iprs_from_docs(updated_docs, states=states)) - set(iprs))
|
||||
# multiple matches, select just one
|
||||
elif start:
|
||||
docs = start
|
||||
|
@ -723,11 +736,12 @@ def search(request):
|
|||
|
||||
return render(request, template, {
|
||||
"q": q,
|
||||
"iprs": iprs,
|
||||
"docs": docs,
|
||||
"doc": doc,
|
||||
"form":form,
|
||||
"states":states
|
||||
"iprs": iprs,
|
||||
"docs": docs,
|
||||
"doc": doc,
|
||||
"form": form,
|
||||
"states": states,
|
||||
"related_iprs": related_iprs,
|
||||
})
|
||||
|
||||
return HttpResponseRedirect(request.path)
|
||||
|
@ -755,13 +769,18 @@ def show(request, id):
|
|||
elif ipr.state.slug != 'posted':
|
||||
raise Http404
|
||||
|
||||
updates_iprs = ipr.relatedipr_source_set.all().order_by('source__time')
|
||||
prev_rel = updates_iprs.last()
|
||||
prev = prev_rel.target.get_child() if prev_rel else None
|
||||
|
||||
return render(request, "ipr/details_view.html", {
|
||||
'ipr': ipr,
|
||||
'prev': prev,
|
||||
'in_force_ipr_rfc': ipr_rfc_number(ipr.time, ipr.is_thirdparty),
|
||||
'tabs': get_details_tabs(ipr, 'Disclosure'),
|
||||
'choices_abc': [ i.desc for i in IprLicenseTypeName.objects.filter(slug__in=['no-license', 'royalty-free', 'reasonable', ]) ],
|
||||
'updates_iprs': ipr.relatedipr_source_set.all(),
|
||||
'updated_by_iprs': ipr.relatedipr_target_set.filter(source__state="posted")
|
||||
'updates_iprs': updates_iprs,
|
||||
'updated_by_iprs': ipr.relatedipr_target_set.filter(source__state="posted").order_by('target__time')
|
||||
})
|
||||
|
||||
def showlist(request):
|
||||
|
|
|
@ -753,6 +753,23 @@ blockquote {
|
|||
}
|
||||
|
||||
|
||||
.table-condensed th.ipr-label {
|
||||
overflow: hidden;
|
||||
clear: left;
|
||||
text-align: right;
|
||||
text-overflow: ellipsis;
|
||||
padding-right: 1em;
|
||||
vertical-align: top;
|
||||
}
|
||||
.table-condensed .ipr-prev {
|
||||
color: #777;
|
||||
background-color: #f0f0f0;
|
||||
vertical-align: top;
|
||||
}
|
||||
.table-condensed .ipr-this {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.rfcmarkup div {
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
|
|
@ -162,7 +162,21 @@
|
|||
<h2>{% cycle section %}. Disclosure of Patent Information{% if form.instance|to_class_name == "ThirdPartyIprDicslosure" %}, if known{% endif %}
|
||||
<small>i.e., patents or patent applications required to be disclosed by Section 5 of RFC8179</small></h2>
|
||||
|
||||
{% if form.patent_info %}
|
||||
{% if form.patent_number %}
|
||||
<p>
|
||||
A. For granted patents or published pending patent applications,
|
||||
please provide the following information:
|
||||
</p>
|
||||
{% bootstrap_field form.patent_number layout='horizontal' %}
|
||||
{% bootstrap_field form.patent_inventor layout='horizontal' %}
|
||||
{% bootstrap_field form.patent_title layout='horizontal' %}
|
||||
{% bootstrap_field form.patent_date layout='horizontal' %}
|
||||
{% bootstrap_field form.patent_notes layout='horizontal' %}
|
||||
|
||||
<p>B. Does your disclosure relate to an unpublished pending patent application?</p>
|
||||
{% bootstrap_field form.has_patent_pending layout='horizontal' %}
|
||||
|
||||
{% elif form.patent_info %}
|
||||
<p>
|
||||
A. For granted patents or published pending patent applications,
|
||||
please provide the following information:
|
||||
|
|
|
@ -73,20 +73,27 @@
|
|||
of the original IPR disclosure.</p>
|
||||
{% endif %}
|
||||
|
||||
{% if updated_by_iprs %}
|
||||
<h2>Updated by</h2>
|
||||
|
||||
{% for item in updated_by_iprs %}
|
||||
<p>
|
||||
This IPR disclosure has been updated by IPR disclosure ID #{{ item.source.id }},
|
||||
"<a href="{% url "ietf.ipr.views.show" id=item.source.id %}">{{ item.source.title }}</a>".
|
||||
</p>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
{% if updates_iprs %}
|
||||
{% if updates_iprs or updated_by_iprs%}
|
||||
<h2>Updates</h2>
|
||||
|
||||
{% if updated_by_iprs %}
|
||||
<dl class="dl-horizontal">
|
||||
<dt>Updated by</dt>
|
||||
<dd>
|
||||
{% for item in updated_by_iprs %}
|
||||
<div>
|
||||
IPR Disclosure ID #{{ item.source.id }},
|
||||
{% if item.source.state.slug == "removed" %}
|
||||
"{{ item.source.title }}" (which was removed at the request of the submitter)
|
||||
{% else %}
|
||||
"<a href="{% url "ietf.ipr.views.show" id=item.source.id %}">{{ item.source.title }}</a>"
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</dl>
|
||||
{% endif %}
|
||||
|
||||
{% if updates_iprs %}
|
||||
<dl class="dl-horizontal">
|
||||
<dt>Updates</dt>
|
||||
<dd>
|
||||
|
@ -101,6 +108,7 @@
|
|||
</div>
|
||||
{% endfor %}
|
||||
</dl>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{% if user|has_role:"Secretariat" and ipr.update_notified_date %}
|
||||
|
@ -113,65 +121,128 @@
|
|||
{% if ipr|to_class_name == "ThirdPartyIprDisclosure" %}Possible{% endif %}
|
||||
Patent Holder/Applicant ("Patent Holder")</h2>
|
||||
|
||||
<dl class="dl-horizontal">
|
||||
<dt>Holder legal name</dt>
|
||||
<dd>{{ ipr.holder_legal_name }}</dd>
|
||||
</dl>
|
||||
<table class="table-condensed col-md-12">
|
||||
{% if prev %}
|
||||
<tr><th class="ipr-prev">Previous (<a href="{% url "ietf.ipr.views.show" id=prev.id %}">#{{prev.id}}</a>)</th><th></th><th>This (#{{ipr.id}})</th></tr>
|
||||
{% endif %}
|
||||
<tr>
|
||||
{% if prev %}<td class="col-md-5 ipr-prev">{{ prev.holder_legal_name }}</td>{% endif %}
|
||||
<th class="col-md-2 ipr-label">Holder legal name</th>
|
||||
<td class="col-md-5 ipr-this">{{ ipr.holder_legal_name }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
{% if ipr.holder_contact_name or ipr.holder_contact_info %}
|
||||
<h2>{% cycle section %}. Patent Holder's Contact for License Application</h2>
|
||||
<h2>{% cycle section %}. Patent Holder's Contact for Licence Application</h2>
|
||||
|
||||
<dl class="dl-horizontal">
|
||||
<dt>Holder contact name</dt>
|
||||
<dd>{{ ipr.holder_contact_name }}</dd>
|
||||
<table class="table-condensed col-md-12">
|
||||
{% if prev %}
|
||||
<tr><th class="ipr-prev">Previous (<a href="{% url "ietf.ipr.views.show" id=prev.id %}">#{{prev.id}}</a>)</th><th></th><th>This (#{{ipr.id}})</th></tr>
|
||||
{% endif %}
|
||||
|
||||
<dt>Holder contact email</dt>
|
||||
<dd>{{ ipr.holder_contact_email }}</dd>
|
||||
<tr>
|
||||
{% if prev %}<td class="col-md-5 ipr-prev">{{ prev.holder_contact_name }}</td>{% endif %}
|
||||
<th class="col-md-2 ipr-label">Holder contact name</th>
|
||||
<td class="col-md-5 ipr-this">{{ ipr.holder_contact_name }}</td>
|
||||
</tr>
|
||||
|
||||
<dt>Holder contact info</dt>
|
||||
<dd>{{ ipr.holder_contact_info|linebreaks }}</dd>
|
||||
</dl>
|
||||
{% endif %}
|
||||
<tr>
|
||||
{% if prev %}<td class="col-md-5 ipr-prev">{{ prev.holder_contact_email }}</td>{% endif %}
|
||||
<th class="col-md-2 ipr-label">Holder contact email</th>
|
||||
<td class="col-md-5 ipr-this">{{ ipr.holder_contact_email }}</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
{% if prev %}<td class="col-md-5 ipr-prev">{{ prev.holder_contact_info|linebreaks }}</td>{% endif %}
|
||||
<th class="col-md-2 ipr-label">Holder contact info</th>
|
||||
<td class="col-md-5 ipr-this">{{ ipr.holder_contact_info|linebreaks }}</td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
{% endif %}
|
||||
|
||||
{% if ipr.ietfer_name or ipr.ietfer_contact_email or ipr.ietfer_contact_info %}
|
||||
<h2>{% cycle section %}. Contact Information for the IETF Participant Whose Personal Belief Triggered this Disclosure</h2>
|
||||
|
||||
<dl class="dl-horizontal">
|
||||
<dt>Name</dt>
|
||||
<dd>{{ ipr.ietfer_name }}</dd>
|
||||
<table class="table-condensed col-md-12">
|
||||
{% if prev %}
|
||||
<tr><th class="ipr-prev">Previous (<a href="{% url "ietf.ipr.views.show" id=prev.id %}">#{{prev.id}}</a>)</th><th></th><th>This (#{{ipr.id}})</th></tr>
|
||||
{% endif %}
|
||||
<tr>
|
||||
{% if prev %}<td class="col-md-5 ipr-prev">{{ prev.ietfer_name }}</td>{% endif %}
|
||||
<th class="col-md-2 ipr-label">Name</th>
|
||||
<td class="col-md-5 ipr-this">{{ ipr.ietfer_name }}</td>
|
||||
</tr>
|
||||
|
||||
<dt>Email</dt>
|
||||
<dd>{{ ipr.ietfer_contact_email }}</dd>
|
||||
<tr>
|
||||
{% if prev %}<td class="col-md-5 ipr-prev">{{ prev.ietfer_contact_email }}</td>{% endif %}
|
||||
<th class="col-md-2 ipr-label">Email</th>
|
||||
<td class="col-md-5 ipr-this">{{ ipr.ietfer_contact_email }}</td>
|
||||
</tr>
|
||||
|
||||
<dt>Other info</dt>
|
||||
<dd>{{ ipr.ietfer_contact_info|linebreaks }}</dd>
|
||||
</dl>
|
||||
<tr>
|
||||
{% if prev %}<td class="col-md-5 ipr-prev">{{ prev.ietfer_contact_info|linebreaks }}</td>{% endif %}
|
||||
<th class="col-md-2 ipr-label">Other info</th>
|
||||
<td class="col-md-5 ipr-this">{{ ipr.ietfer_contact_info|linebreaks }}</td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
{% endif %}
|
||||
|
||||
{% if ipr.iprdocrel_set.all or ipr.other_designations %}
|
||||
<h2>{% cycle section %}. IETF Document or Other Contribution to Which this IPR Disclosure Relates</h2>
|
||||
|
||||
<dl class="dl-horizontal">
|
||||
{% for iprdocrel in ipr.iprdocrel_set.all %}
|
||||
<dt>{{ iprdocrel.doc_type }}</dt>
|
||||
<dd>
|
||||
<div>{{ iprdocrel.formatted_name }} ("{{ iprdocrel.document.document.title }}")</div>
|
||||
<table class="table-condensed col-md-12">
|
||||
{% if prev %}
|
||||
<tr><th class="ipr-prev">Previous (<a href="{% url "ietf.ipr.views.show" id=prev.id %}">#{{prev.id}}</a>)</th><th></th><th>This (#{{ipr.id}})</th></tr>
|
||||
{% endif %}
|
||||
<tr>
|
||||
|
||||
{% if iprdocrel.revisions %}
|
||||
<div>Revisions: {{ iprdocrel.revisions }}</div>
|
||||
{% endif %}
|
||||
{% if prev %}
|
||||
<td class="col-md-5 ipr-prev">
|
||||
{% for iprdocrel in prev.iprdocrel_set.all %}
|
||||
<b>{{ iprdocrel.doc_type }}:</b>
|
||||
{{ iprdocrel.formatted_name }} ("{{ iprdocrel.document.document.title }}")
|
||||
|
||||
{% if iprdocrel.sections %}
|
||||
<div>Sections: {{ iprdocrel.sections }}</div>
|
||||
{% endif %}
|
||||
</dd>
|
||||
{% endfor %}
|
||||
{% if iprdocrel.revisions %}
|
||||
<div>Revisions: {{ iprdocrel.revisions }}</div>
|
||||
{% endif %}
|
||||
|
||||
{% if ipr.other_designations %}
|
||||
<dt>Designations for Other Contributions</dt>
|
||||
<dd>{{ ipr.other_designations }}</dd>
|
||||
{% endif %}
|
||||
</dl>
|
||||
{% if iprdocrel.sections %}
|
||||
<div>Sections: {{ iprdocrel.sections }}</div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
{% if prev.other_designations %}
|
||||
<b>Designations for Other Contributions</b>
|
||||
{{ prev.other_designations }}
|
||||
{% endif %}
|
||||
</td>
|
||||
{% endif %}
|
||||
|
||||
<th class="col-md-2 ipr-label"></th>
|
||||
|
||||
<td class="col-md-5 ipr-this">
|
||||
{% for iprdocrel in ipr.iprdocrel_set.all %}
|
||||
<b>{{ iprdocrel.doc_type }}:</b>
|
||||
{{ iprdocrel.formatted_name }} ("{{ iprdocrel.document.document.title }}")
|
||||
|
||||
{% if iprdocrel.revisions %}
|
||||
<div>Revisions: {{ iprdocrel.revisions }}</div>
|
||||
{% endif %}
|
||||
|
||||
{% if iprdocrel.sections %}
|
||||
<div>Sections: {{ iprdocrel.sections }}</div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
{% if ipr.other_designations %}
|
||||
<dt>Designations for Other Contributions</dt>
|
||||
<dd>{{ ipr.other_designations }}</dd>
|
||||
{% endif %}
|
||||
</td>
|
||||
<tr>
|
||||
</table>
|
||||
{% endif %}
|
||||
|
||||
{% if ipr.patent_info or ipr.has_patent_pending %}
|
||||
|
@ -179,17 +250,29 @@
|
|||
|
||||
<p>A. For granted patents or published pending patent applications, please provide the following information:</p>
|
||||
|
||||
<dl class="dl-horizontal">
|
||||
<dt>Patent, Serial, Publication, Registration, or Application/File number(s)</dt>
|
||||
<dd>{{ ipr.patent_info|linebreaks }}</dd>
|
||||
</dl>
|
||||
|
||||
<table class="table-condensed col-md-12">
|
||||
{% if prev %}
|
||||
<tr><th class="ipr-prev">Previous (<a href="{% url "ietf.ipr.views.show" id=prev.id %}">#{{prev.id}}</a>)</th><th></th><th>This (#{{ipr.id}})</th></tr>
|
||||
{% endif %}
|
||||
<tr>
|
||||
{% if prev %}<td class="col-md-5 ipr-prev">{{ prev.patent_info|linebreaks }}</td>{% endif %}
|
||||
<th class="col-md-2 ipr-label">Patent, Serial, Publication, Registration, or Application/File number(s)</th>
|
||||
<td class="col-md-5 ipr-this">{{ ipr.patent_info|linebreaks }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p>B. Does this disclosure relate to an unpublished pending patent application?:</p>
|
||||
|
||||
<dl class="dl-horizontal">
|
||||
<dt>Has patent pending</dt>
|
||||
<dd>{{ ipr.has_patent_pending|yesno:"Yes,No" }}</dd>
|
||||
</dl>
|
||||
<table class="table-condensed col-md-12">
|
||||
{% if prev %}
|
||||
<tr><th class="ipr-prev">Previous (<a href="{% url "ietf.ipr.views.show" id=prev.id %}">#{{prev.id}}</a>)</th><th></th><th>This (#{{ipr.id}})</th></tr>
|
||||
{% endif %}
|
||||
<tr>
|
||||
{% if prev %}<td class="col-md-5 ipr-prev">{{ prev.has_patent_pending|yesno:"Yes,No" }}</td>{% endif %}
|
||||
<th class="col-md-2 ipr-label">Has patent pending</th>
|
||||
<td class="col-md-5 ipr-this">{{ ipr.has_patent_pending|yesno:"Yes,No" }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
{% endif %}
|
||||
|
||||
{% if ipr.licensing %}
|
||||
|
@ -204,23 +287,32 @@
|
|||
specification, is as follows(select one licensing declaration option only):
|
||||
</p>
|
||||
|
||||
{% if ipr.licensing.slug == "provided-later" %}
|
||||
{% if prev.licensing.slug == "provided-later" or ipr.licensing.slug == "provided-later" %}
|
||||
<div>
|
||||
Possible licencing choices a), b), and c) when Licencing Declaration to be Provided Later:
|
||||
Possible licensing choices a), b), and c) when Licensing Declaration to be Provided Later:
|
||||
<ul style="list-style: none">
|
||||
{% for desc in choices_abc %}
|
||||
<li>{{ desc}}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
<dl class="dl-horizontal">
|
||||
<dt>Licensing</dt>
|
||||
<dd>{% if ipr.licensing.slug == "provided-later" %}{{ ipr.licensing.desc|slice:"2:"|slice:":117" }}){% else %}{{ ipr.licensing.desc|slice:"2:" }}{% endif %}</dd>
|
||||
|
||||
<dt>Licensing information, comments, notes, or URL for further information</dt>
|
||||
<dd>{{ ipr.licensing_comments|default:"(No information submitted)"|linebreaks }}</dd>
|
||||
</dl>
|
||||
<table class="table-condensed col-md-12">
|
||||
{% if prev %}
|
||||
<tr><th class="ipr-prev">Previous (<a href="{% url "ietf.ipr.views.show" id=prev.id %}">#{{prev.id}}</a>)</th><th></th><th>This (#{{ipr.id}})</th></tr>
|
||||
{% endif %}
|
||||
<tr>
|
||||
{% if prev %}<td class="col-md-5 ipr-prev">{% if prev.licensing.slug == "provided-later" %}{{ prev.licensing.desc|slice:"2:"|slice:":117" }}){% else %}{{ prev.licensing.desc|slice:"2:" }}{% endif %}</td>{% endif %}
|
||||
<th class="col-md-2 ipr-label">Licensing</th>
|
||||
<td class="col-md-5 ipr-this">{% if ipr.licensing.slug == "provided-later" %}{{ ipr.licensing.desc|slice:"2:"|slice:":117" }}){% else %}{{ ipr.licensing.desc|slice:"2:" }}{% endif %}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
{% if prev %}<td class="col-md-5 ipr-prev">{{ prev.licensing_comments|default:"(No information submitted)"|linebreaks }}</td>{% endif %}
|
||||
<th class="col-md-2 ipr-label">Licensing information, comments, notes, or URL for further information</th>
|
||||
<td class="col-md-5 ipr-this">{{ ipr.licensing_comments|default:"(No information submitted)"|linebreaks }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p>Note: The individual submitting this template represents and warrants
|
||||
that he or she is authorized by the Patent Holder to agree to the
|
||||
|
@ -229,33 +321,54 @@
|
|||
{% elif ipr.statement %}
|
||||
<h2>{% cycle section %}. Statement</h2>
|
||||
|
||||
<dl class="dl-horizontal">
|
||||
<dt>Statement</dt>
|
||||
<dd>{{ ipr.statement|linebreaks }}</dd>
|
||||
</dl>
|
||||
<table class="table-condensed col-md-12">
|
||||
{% if prev %}
|
||||
<tr><th class="ipr-prev">Previous (<a href="{% url "ietf.ipr.views.show" id=prev.id %}">#{{prev.id}}</a>)</th><th></th><th>This (#{{ipr.id}})</th></tr>
|
||||
{% endif %}
|
||||
<tr>
|
||||
{% if prev %}<td class="col-md-5 ipr-prev">{{ prev.statement|linebreaks }}</td>{% endif %}
|
||||
<th class="col-md-2 ipr-label">Statement</th>
|
||||
<td class="col-md-5 ipr-this">{{ ipr.statement|linebreaks }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
{% endif %}
|
||||
|
||||
<h2>{% cycle section %}. Contact Information of Submitter of this Form</h2>
|
||||
|
||||
<dl class="dl-horizontal">
|
||||
<dt>Submitter name</dt>
|
||||
<dd>{{ ipr.submitter_name }}</dd>
|
||||
<table class="table-condensed col-md-12">
|
||||
{% if prev %}
|
||||
<tr><th class="ipr-prev">Previous (<a href="{% url "ietf.ipr.views.show" id=prev.id %}">#{{prev.id}}</a>)</th><th></th><th>This (#{{ipr.id}})</th></tr>
|
||||
{% endif %}
|
||||
<tr>
|
||||
{% if prev %}<td class="col-md-5 ipr-prev">{{ prev.submitter_name }}</td>{% endif %}
|
||||
<th class="col-md-2 ipr-label">Submitter name</th>
|
||||
<td class="col-md-5 ipr-this">{{ ipr.submitter_name }}</td>
|
||||
</tr>
|
||||
|
||||
<dt>Submitter email</dt>
|
||||
<dd>{{ ipr.submitter_email }}</dd>
|
||||
</dl>
|
||||
<tr>
|
||||
{% if prev %}<td class="col-md-5 ipr-prev">{{ prev.submitter_email }}</td>{% endif %}
|
||||
<th class="col-md-2 ipr-label">Submitter email</th>
|
||||
<td class="col-md-5 ipr-this">{{ ipr.submitter_email }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
{% if ipr.notes %}
|
||||
<h2>{% cycle section %}. Other Notes</h2>
|
||||
|
||||
<dl class="dl-horizontal">
|
||||
<dt>Additional notes</dt>
|
||||
<dd>{{ ipr.notes|linebreaks }}</dd>
|
||||
</dl>
|
||||
<table class="table-condensed col-md-12">
|
||||
{% if prev %}
|
||||
<tr><th class="ipr-prev">Previous (<a href="{% url "ietf.ipr.views.show" id=prev.id %}">#{{prev.id}}</a>)</th><th></th><th>This (#{{ipr.id}})</th></tr>
|
||||
{% endif %}
|
||||
<tr>
|
||||
{% if prev %}<td class="col-md-5 ipr-prev">{{ prev.notes|linebreaks }}</td>{% endif %}
|
||||
<th class="col-md-2 ipr-label">Additional notes</th>
|
||||
<td class="col-md-5 ipr-this">{{ ipr.notes|linebreaks }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<p class="help-block">Only those sections of the relevant entry form where the submitter provided information are displayed.</p>
|
||||
|
||||
</div>
|
||||
{% endblock content %}
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
<link rel="stylesheet" href="{% static "jquery.tablesorter/css/theme.bootstrap.min.css" %}">
|
||||
{% endblock %}
|
||||
|
||||
{% block search_header %}Draft search results{% endblock %}
|
||||
{% block search_header %}Document IPR search results <small>for {{doc}}</small>{% endblock %}
|
||||
|
||||
{% block search_result %}
|
||||
<p class="alert alert-info">Total number of IPR disclosures found: <b>{{ iprs|length }}</b>.</p>
|
||||
|
@ -35,6 +35,12 @@
|
|||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% if related_iprs %}
|
||||
<p>
|
||||
<i>IPR declarations exist for related documents, <a href="#related">see below</a>.
|
||||
These cannot be assumed to apply to the current document without closer inspection.</i>
|
||||
</p>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
<p class="alert alert-info">Total number of documents searched: <b>{{ docs|length}}</b>.</p>
|
||||
|
@ -85,8 +91,35 @@
|
|||
{% endfor %}
|
||||
</table>
|
||||
|
||||
{% if related_iprs %}
|
||||
<p class="alert alert-info" id="related">Total number of possibly related IPR disclosures found: <b>{{ related_iprs|length }}</b>.</p>
|
||||
|
||||
<table class="table table-condensed table-striped tablesorter">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Date</th>
|
||||
<th>ID</th>
|
||||
<th>Statement</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
{% for ipr in related_iprs %}
|
||||
<tr>
|
||||
<td class="text-nowrap">{{ ipr.time|date:"Y-m-d" }}</td>
|
||||
<td>{{ ipr.id }}</td>
|
||||
<td><a href="{% url "ietf.ipr.views.show" id=ipr.id %}">{{ ipr.title }}</a>
|
||||
{% if ipr.updates %} <br/>(Updates ID#: {% for upd in ipr.updates %}{{upd.target_id}}{% if not forloop.last %}, {% endif %}{% endfor %}){% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% endif %}
|
||||
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block js %}
|
||||
<script src="{% static "jquery.tablesorter/js/jquery.tablesorter.combined.min.js" %}"></script>
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
|
|
|
@ -331,7 +331,7 @@ def make_test_data():
|
|||
title="Statement regarding rights",
|
||||
holder_legal_name="Native Martians United",
|
||||
state=IprDisclosureStateName.objects.get(slug='posted'),
|
||||
patent_info='US12345',
|
||||
patent_info='Number: US12345\nTitle: A method of transfering bits\nInventor: A. Nonymous\nDate: 2000-01-01',
|
||||
holder_contact_name='George',
|
||||
holder_contact_email='george@acme.com',
|
||||
holder_contact_info='14 Main Street\nEarth',
|
||||
|
|
|
@ -140,4 +140,37 @@ def decode(raw):
|
|||
text = raw.decode('latin-1')
|
||||
#
|
||||
return text
|
||||
|
||||
|
||||
def text_to_dict(t):
|
||||
"Converts text with RFC2822-formatted header fields into a dictionary-like object."
|
||||
# ensure we're handed a unicode parameter
|
||||
assert isinstance(t, six.text_type)
|
||||
d = {}
|
||||
# Return {} for malformed input
|
||||
if not len(t.lstrip()) == len(t):
|
||||
return {}
|
||||
lines = t.splitlines()
|
||||
items = []
|
||||
# unfold folded lines
|
||||
for l in lines:
|
||||
if l[0].isspace():
|
||||
if items:
|
||||
items[-1] += l
|
||||
else:
|
||||
return {}
|
||||
else:
|
||||
items.append(l)
|
||||
for i in items:
|
||||
if re.match('^[A-Za-z0-9-]+: ', i):
|
||||
k, v = i.split(': ', 1)
|
||||
d[k] = v
|
||||
else:
|
||||
return {}
|
||||
return d
|
||||
|
||||
def dict_to_text(d):
|
||||
"Convert a dictionary to RFC2822-formatted text"
|
||||
t = ""
|
||||
for k, v in d.items():
|
||||
t += "%s: %s\n" % (k, v)
|
||||
return t
|
||||
|
|
Loading…
Reference in a new issue