291 lines
12 KiB
Python
291 lines
12 KiB
Python
import datetime
|
|
import email
|
|
|
|
from django import forms
|
|
|
|
from ietf.group.models import Group
|
|
from ietf.ipr.mail import utc_from_string
|
|
from ietf.ipr.fields import (AutocompletedIprDisclosuresField, AutocompletedDraftField,
|
|
AutocompletedRfcField)
|
|
from ietf.ipr.models import (IprDocRel, IprDisclosureBase, HolderIprDisclosure,
|
|
GenericIprDisclosure, ThirdPartyIprDisclosure, NonDocSpecificIprDisclosure,
|
|
IprLicenseTypeName, IprDisclosureStateName)
|
|
from ietf.message.models import Message
|
|
|
|
# ----------------------------------------------------------------
|
|
# Globals
|
|
# ----------------------------------------------------------------
|
|
STATE_CHOICES = [ (x.slug, x.name) for x in IprDisclosureStateName.objects.all() ]
|
|
STATE_CHOICES.insert(0,('all','All States'))
|
|
|
|
# ----------------------------------------------------------------
|
|
# Base Classes
|
|
# ----------------------------------------------------------------
|
|
class CustomModelChoiceField(forms.ModelChoiceField):
|
|
def label_from_instance(self, obj):
|
|
return obj.desc
|
|
|
|
class GroupModelChoiceField(forms.ModelChoiceField):
|
|
'''Custom ModelChoiceField that displays group acronyms as choices.'''
|
|
def label_from_instance(self, obj):
|
|
return obj.acronym
|
|
|
|
class MessageModelChoiceField(forms.ModelChoiceField):
|
|
'''Custom ModelChoiceField that displays messages.'''
|
|
def label_from_instance(self, obj):
|
|
date = obj.time.strftime("%Y-%m-%d")
|
|
if len(obj.subject) > 45:
|
|
subject = obj.subject[:43] + '....'
|
|
else:
|
|
subject = obj.subject
|
|
return '{} - {}'.format(date,subject)
|
|
|
|
# ----------------------------------------------------------------
|
|
# Forms
|
|
# ----------------------------------------------------------------
|
|
class AddCommentForm(forms.Form):
|
|
private = forms.BooleanField(required=False,help_text="If this box is checked the comment will not appear in the disclosure's public history view.")
|
|
comment = forms.CharField(required=True, widget=forms.Textarea)
|
|
|
|
class AddEmailForm(forms.Form):
|
|
direction = forms.ChoiceField(choices=(("incoming", "Incoming"), ("outgoing", "Outgoing")),
|
|
widget=forms.RadioSelect)
|
|
in_reply_to = MessageModelChoiceField(queryset=Message.objects,label="In Reply To",required=False)
|
|
message = forms.CharField(required=True, widget=forms.Textarea)
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
self.ipr = kwargs.pop('ipr', None)
|
|
super(AddEmailForm, self).__init__(*args, **kwargs)
|
|
|
|
if self.ipr:
|
|
self.fields['in_reply_to'].queryset = Message.objects.filter(msgevents__disclosure__id=self.ipr.pk)
|
|
|
|
def clean_message(self):
|
|
'''Returns a ietf.message.models.Message object'''
|
|
text = self.cleaned_data['message']
|
|
message = email.message_from_string(text)
|
|
for field in ('to','from','subject','date'):
|
|
if not message[field]:
|
|
raise forms.ValidationError('Error parsing email: {} field not found.'.format(field))
|
|
date = utc_from_string(message['date'])
|
|
if not isinstance(date,datetime.datetime):
|
|
raise forms.ValidationError('Error parsing email date field')
|
|
return message
|
|
|
|
def clean(self):
|
|
if any(self.errors):
|
|
return self.cleaned_data
|
|
super(AddEmailForm, self).clean()
|
|
in_reply_to = self.cleaned_data['in_reply_to']
|
|
message = self.cleaned_data['message']
|
|
direction = self.cleaned_data['direction']
|
|
if in_reply_to:
|
|
if direction != 'incoming':
|
|
raise forms.ValidationError('Only incoming messages can have In Reply To selected')
|
|
date = utc_from_string(message['date'])
|
|
if date < in_reply_to.time:
|
|
raise forms.ValidationError('The incoming message must have a date later than the message it is replying to')
|
|
|
|
return self.cleaned_data
|
|
|
|
class DraftForm(forms.ModelForm):
|
|
document = AutocompletedDraftField(required=False)
|
|
|
|
class Meta:
|
|
model = IprDocRel
|
|
fields = '__all__'
|
|
widgets = {
|
|
'sections': forms.TextInput(),
|
|
}
|
|
help_texts = { 'sections': 'Sections' }
|
|
|
|
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
|
|
otherwise create a GenericIprDisclosure object."""
|
|
compliant = forms.BooleanField(required=False)
|
|
holder_legal_name = forms.CharField(max_length=255)
|
|
notes = forms.CharField(max_length=255,widget=forms.Textarea,required=False)
|
|
other_designations = forms.CharField(max_length=255,required=False)
|
|
holder_contact_name = forms.CharField(max_length=255)
|
|
holder_contact_email = forms.EmailField()
|
|
holder_contact_info = forms.CharField(max_length=255,widget=forms.Textarea,required=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)
|
|
has_patent_pending = forms.BooleanField(required=False)
|
|
statement = forms.CharField(max_length=255,widget=forms.Textarea,required=False)
|
|
updates = AutocompletedIprDisclosuresField(required=False)
|
|
same_as_ii_above = forms.BooleanField(required=False)
|
|
|
|
def __init__(self,*args,**kwargs):
|
|
super(GenericDisclosureForm, self).__init__(*args,**kwargs)
|
|
self.fields['compliant'].initial = True
|
|
|
|
def clean(self):
|
|
super(GenericDisclosureForm, self).clean()
|
|
cleaned_data = self.cleaned_data
|
|
|
|
# if same_as_above not checked require submitted
|
|
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')
|
|
|
|
return cleaned_data
|
|
|
|
def save(self, *args, **kwargs):
|
|
nargs = self.cleaned_data.copy()
|
|
same_as_ii_above = nargs.get('same_as_ii_above')
|
|
del nargs['same_as_ii_above']
|
|
|
|
if self.cleaned_data.get('patent_info'):
|
|
obj = NonDocSpecificIprDisclosure(**nargs)
|
|
else:
|
|
del nargs['patent_info']
|
|
del nargs['has_patent_pending']
|
|
obj = GenericIprDisclosure(**nargs)
|
|
|
|
if same_as_ii_above == True:
|
|
obj.submitter_name = obj.holder_contact_name
|
|
obj.submitter_email = obj.holder_contact_email
|
|
|
|
if kwargs.get('commit',True):
|
|
obj.save()
|
|
|
|
return obj
|
|
|
|
class IprDisclosureFormBase(forms.ModelForm):
|
|
"""Base form for Holder and ThirdParty disclosures"""
|
|
updates = AutocompletedIprDisclosuresField(required=False)
|
|
same_as_ii_above = forms.BooleanField(required=False)
|
|
|
|
def __init__(self,*args,**kwargs):
|
|
super(IprDisclosureFormBase, self).__init__(*args,**kwargs)
|
|
self.fields['submitter_name'].required = False
|
|
self.fields['submitter_email'].required = False
|
|
self.fields['compliant'].initial = True
|
|
|
|
class Meta:
|
|
"""This will be overridden"""
|
|
model = IprDisclosureBase
|
|
fields = '__all__'
|
|
|
|
def clean(self):
|
|
super(IprDisclosureFormBase, self).clean()
|
|
cleaned_data = self.cleaned_data
|
|
|
|
if not self.instance.pk:
|
|
# when entering a new disclosure, if same_as_above not checked require submitted
|
|
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')
|
|
|
|
return cleaned_data
|
|
|
|
class HolderIprDisclosureForm(IprDisclosureFormBase):
|
|
licensing = CustomModelChoiceField(IprLicenseTypeName.objects.all(),
|
|
widget=forms.RadioSelect,empty_label=None)
|
|
|
|
class Meta:
|
|
model = HolderIprDisclosure
|
|
exclude = [ 'by','docs','state','rel' ]
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
super(HolderIprDisclosureForm, self).__init__(*args, **kwargs)
|
|
if self.instance.pk:
|
|
# editing existing disclosure
|
|
self.fields['patent_info'].required = False
|
|
self.fields['holder_contact_name'].required = False
|
|
self.fields['holder_contact_email'].required = False
|
|
else:
|
|
# entering new disclosure
|
|
self.fields['licensing'].queryset = IprLicenseTypeName.objects.exclude(slug='none-selected')
|
|
|
|
def clean(self):
|
|
super(HolderIprDisclosureForm, self).clean()
|
|
cleaned_data = self.cleaned_data
|
|
if not self.data.get('draft-0-document') and not self.data.get('rfc-0-document') and not cleaned_data.get('other_designations'):
|
|
raise forms.ValidationError('You need to specify a contribution in Section IV')
|
|
return cleaned_data
|
|
|
|
def save(self, *args, **kwargs):
|
|
obj = super(IprDisclosureFormBase, self).save(*args,commit=False)
|
|
if self.cleaned_data.get('same_as_ii_above') == True:
|
|
obj.submitter_name = obj.holder_contact_name
|
|
obj.submitter_email = obj.holder_contact_email
|
|
if kwargs.get('commit',True):
|
|
obj.save()
|
|
return obj
|
|
|
|
class GenericIprDisclosureForm(IprDisclosureFormBase):
|
|
"""Use for editing a GenericIprDisclosure"""
|
|
class Meta:
|
|
model = GenericIprDisclosure
|
|
exclude = [ 'by','docs','state','rel' ]
|
|
|
|
class MessageModelForm(forms.ModelForm):
|
|
response_due = forms.DateField(required=False,help_text='The date which a response is due')
|
|
|
|
class Meta:
|
|
model = Message
|
|
fields = ['to','frm','cc','bcc','reply_to','subject','body']
|
|
exclude = ['time','by','content_type','related_groups','related_docs']
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
super(MessageModelForm, self).__init__(*args, **kwargs)
|
|
self.fields['frm'].label='From'
|
|
self.fields['frm'].widget.attrs['readonly'] = True
|
|
self.fields['reply_to'].widget.attrs['readonly'] = True
|
|
|
|
class NonDocSpecificIprDisclosureForm(IprDisclosureFormBase):
|
|
class Meta:
|
|
model = NonDocSpecificIprDisclosure
|
|
exclude = [ 'by','docs','state','rel' ]
|
|
|
|
class NotifyForm(forms.Form):
|
|
type = forms.CharField(widget=forms.HiddenInput)
|
|
text = forms.CharField(widget=forms.Textarea)
|
|
|
|
class RfcForm(DraftForm):
|
|
document = AutocompletedRfcField(required=False)
|
|
|
|
class Meta(DraftForm.Meta):
|
|
exclude = ('revisions',)
|
|
|
|
class ThirdPartyIprDisclosureForm(IprDisclosureFormBase):
|
|
class Meta:
|
|
model = ThirdPartyIprDisclosure
|
|
exclude = [ 'by','docs','state','rel' ]
|
|
|
|
def clean(self):
|
|
super(ThirdPartyIprDisclosureForm, self).clean()
|
|
cleaned_data = self.cleaned_data
|
|
if not self.data.get('draft-0-document') and not self.data.get('rfc-0-document') and not cleaned_data.get('other_designations'):
|
|
raise forms.ValidationError('You need to specify a contribution in Section III')
|
|
return cleaned_data
|
|
|
|
def save(self, *args, **kwargs):
|
|
obj = super(ThirdPartyIprDisclosureForm, self).save(*args,commit=False)
|
|
if self.cleaned_data.get('same_as_ii_above') == True:
|
|
obj.submitter_name = obj.ietfer_name
|
|
obj.submitter_email = obj.ietfer_contact_email
|
|
if kwargs.get('commit',True):
|
|
obj.save()
|
|
|
|
return obj
|
|
|
|
class SearchForm(forms.Form):
|
|
state = forms.MultipleChoiceField(choices=STATE_CHOICES,widget=forms.CheckboxSelectMultiple,required=False)
|
|
draft = forms.CharField(max_length=128,required=False)
|
|
rfc = forms.IntegerField(required=False)
|
|
holder = forms.CharField(max_length=128,required=False)
|
|
patent = forms.CharField(max_length=128,required=False)
|
|
group = GroupModelChoiceField(label="Working group name",queryset=Group.objects.filter(type='wg').order_by('acronym'),required=False)
|
|
doctitle = forms.CharField(max_length=128,required=False)
|
|
iprtitle = forms.CharField(max_length=128,required=False)
|
|
|
|
class StateForm(forms.Form):
|
|
state = forms.ModelChoiceField(queryset=IprDisclosureStateName.objects,label="New State",empty_label=None)
|
|
private = forms.BooleanField(required=False,help_text="If this box is checked the comment will not appear in the disclosure's public history view.")
|
|
comment = forms.CharField(required=False, widget=forms.Textarea)
|