from django import forms from django.core.exceptions import ValidationError from django.utils.http import urlquote from django.utils import timezone from haystack.forms import ModelSearchForm from floppyforms import widgets import contacts as contact_constants from contacts.models import ( BookOwner, Contact, ContactField, LogEntry, Tag, ) class ContactForm(forms.ModelForm): class Meta: model = Contact fields = ('name','notes','tags', 'should_surface', 'reminder_frequency') widgets = { 'tags': forms.CheckboxSelectMultiple(), 'notes': forms.Textarea(attrs={'rows':3}), } def __init__(self, *args, **kwargs): document_items = None self.user = kwargs.pop('user', None) if kwargs.get('data'): document_items = dict((key, value) for key, value in kwargs.get('data').items() if key.startswith('document')) self.book = kwargs.pop('book') tag_choices = kwargs.pop('tag_choices') super(ContactForm, self).__init__(*args, **kwargs) choices = Tag.objects.filter(book=self.book).values_list('id', 'tag') self.fields['tags'].choices = tag_choices self.fields['deleted_fields'] = forms.CharField(required=False) if document_items: for item in document_items: parts = item.split('_') field_category = parts[1] if len(parts) == 4: if parts[3] == 'pref': self.fields[item] = forms.BooleanField() if parts[3] == 'label': self.fields[item] = forms.CharField(max_length=255) else: if field_category == contact_constants.FIELD_TYPE_EMAIL: self.fields[item] = forms.EmailField(max_length=255) if field_category == contact_constants.FIELD_TYPE_URL: self.fields[item] = forms.URLField(max_length=255) if field_category == contact_constants.FIELD_TYPE_DATE: self.fields[item] = forms.DateField() else: self.fields[item] = forms.CharField() def clean(self): self.has_changed_list = [] # Start by taking care of the contact object fields if self.cleaned_data.get('name') != self.instance.name: self.has_changed_list.append('Name') if self.cleaned_data.get('notes') != self.instance.notes: self.has_changed_list.append('Notes') if self.cleaned_data.get('should_surface') != self.instance.should_surface: self.has_changed_list.append('Send Contact Reminders') if self.cleaned_data.get('reminder_frequency') != self.instance.reminder_frequency: self.has_changed_list.append('Reminder Frequency') # Deal with deleted fields has_changed_list = [] for field_id in self.cleaned_data.get('deleted_fields', '').split(','): if field_id: try: field = ContactField.objects.get( contact=self.instance, id=field_id, ) has_changed_list.append(field.label) field.delete() except ContactField.DoesNotExist: pass # note_str = 'Deleted ' + ', '.join(has_changed_list) # LogEntry.objects.create( # contact = self.instance, # logged_by = self.user, # kind = 'edit', # notes = note_str, # ) # Prep the contact fields for saving self.instance.book = self.book document_items = None document_items = dict((key, value) for key, value in self.cleaned_data.items() if key.startswith('document')) self.document_field_dicts = {} pref_dict = { contact_constants.FIELD_TYPE_EMAIL: False, contact_constants.FIELD_TYPE_TWITTER: False, contact_constants.FIELD_TYPE_URL: False, contact_constants.FIELD_TYPE_PHONE: False, contact_constants.FIELD_TYPE_ADDRESS: False, } if document_items: for item in document_items: parts = item.split('_') field_id = parts[2] field_type = parts[1] field_dict = self.document_field_dicts.get(field_id, {}) field_dict['type'] = field_type if len(parts) == 3: field_dict['value'] = document_items[item] if len(parts) == 4: if parts[3] == 'label': field_dict['label'] = document_items[item] if parts[3] == 'pref': if document_items.get(item) and pref_dict.get(field_type): raise ValidationError( 'Only one {} can be preferred'.format(field_type), ) else: field_dict['pref'] = document_items[item] pref_dict[field_type] = True self.document_field_dicts[field_id] = field_dict return super(ContactForm, self).clean() def save(self, commit=True): response = super(ContactForm, self).save(commit=commit) for item in self.document_field_dicts: item_dict = self.document_field_dicts[item] if item.startswith('new') and item_dict.get('value') and item_dict.get('label'): field_object = ContactField.objects.create( kind=item_dict['type'], contact=self.instance, preferred=item_dict.get('pref', False), value = item_dict['value'], label = item_dict['label'], ) field_object.save() self.has_changed_list.append(field_object.label) else: if item_dict['type'] == contact_constants.FIELD_TYPE_DATE: item_dict['value'] = item_dict['value'].strftime('%Y-%m-%d') field_object = ContactField.objects.get( id=item, contact=self.instance, kind=item_dict['type'], ) if not ( field_object.value == item_dict['value'] and field_object.label == item_dict['label'] and field_object.preferred == item_dict.get('pref', False) ): field_object.value = item_dict['value'] field_object.label = item_dict['label'] field_object.preferred = item_dict.get('pref', False) self.has_changed_list.append(field_object.label) field_object.save() if self.has_changed_list: note_str = 'Updated ' + ', '.join(self.has_changed_list) LogEntry.objects.create( contact = self.instance, logged_by = self.user, kind = 'edit', notes = note_str, time = timezone.now(), ) return response class LogEntryForm(forms.ModelForm): USER_SELECTABLE_CHOICES = ( ('twitter', 'Twitter'), ('tumblr', 'Tumblr'), ('facebook', 'Facebook'), ('email', 'Email'), ('in person', 'In Person'), ('website', 'Website'), ('other', 'Other'), ) kind = forms.ChoiceField(choices=USER_SELECTABLE_CHOICES) class Meta: model = LogEntry fields = ['kind','link','notes', 'time'] widgets = { 'notes': forms.Textarea(attrs={'rows':1}), 'time': widgets.DateInput(attrs={'class':'form-control'}), } class TagForm(forms.ModelForm): class Meta: model = Tag fields = ['tag', 'color'] def clean(self): if self.cleaned_data.get('color') and len(self.cleaned_data.get('color')) > 7: raise ValidationError("Hex colors must be six digits or less!") if self.cleaned_data.get('color') and not self.cleaned_data.get('color').startswith('#'): raise ValidationError("Hex must start with #!") return self.cleaned_data class MultiContactForm(forms.Form): def __init__(self, *args, **kwargs): contact_ids = kwargs.pop('contact_ids') super(MultiContactForm, self).__init__(*args, **kwargs) for contact_id in contact_ids: self.fields['contact_%s' % (contact_id,)] = forms.BooleanField( required=False, ) class MultiTagForm(forms.Form): def __init__(self, *args, **kwargs): tag_ids = kwargs.pop('tag_ids') super(MultiTagForm, self).__init__(*args, **kwargs) for tag_id in tag_ids: self.fields['tag_%s' % (tag_id,)] = forms.BooleanField(required=False) class BookSettingsForm(forms.ModelForm): book_name = forms.CharField(max_length=100, required=True) class Meta: model = BookOwner fields = [ 'send_contact_reminders', 'send_birthday_reminders', 'check_twitter_dms', 'check_twitter_mentions', 'check_foursquare', 'weekly_reminder_day', ] class UploadForm(forms.Form): upload_url = forms.CharField(required=True)