diff --git a/opentech/public/people/migrations/0003_update_contact_information.py b/opentech/public/people/migrations/0003_update_contact_information.py new file mode 100644 index 0000000000000000000000000000000000000000..eaf3d477ce5ef807cec4831df65343d2089e35b8 --- /dev/null +++ b/opentech/public/people/migrations/0003_update_contact_information.py @@ -0,0 +1,39 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.8 on 2018-01-05 17:34 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion +import modelcluster.fields + + +class Migration(migrations.Migration): + + dependencies = [ + ('people', '0002_add_header_image'), + ] + + operations = [ + migrations.CreateModel( + name='PersonContactInfomation', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('sort_order', models.IntegerField(blank=True, editable=False, null=True)), + ('contact_method', models.CharField(blank=True, choices=[('irc', 'IRC'), ('im_jabber_xmpp', 'IM/Jabber/XMPP'), ('phone', 'Phone'), ('pgp', 'PGP fingerprint'), ('otr', 'OTR fingerprint')], max_length=255)), + ('other_method', models.CharField(blank=True, max_length=255, verbose_name='Other')), + ('contact_detail', models.CharField(max_length=255)), + ('page', modelcluster.fields.ParentalKey(on_delete=django.db.models.deletion.CASCADE, related_name='contact_details', to='people.PersonPage')), + ], + options={ + 'ordering': ['sort_order'], + 'abstract': False, + }, + ), + migrations.RemoveField( + model_name='personpagephonenumber', + name='page', + ), + migrations.DeleteModel( + name='PersonPagePhoneNumber', + ), + ] diff --git a/opentech/public/people/migrations/0004_funding.py b/opentech/public/people/migrations/0004_funding.py new file mode 100644 index 0000000000000000000000000000000000000000..55de7f9893f22efa21be3836d0b621a1faab9e01 --- /dev/null +++ b/opentech/public/people/migrations/0004_funding.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.8 on 2018-01-10 16:25 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion +import modelcluster.fields + + +class Migration(migrations.Migration): + + dependencies = [ + ('wagtailcore', '0040_page_draft_title'), + ('people', '0003_update_contact_information'), + ] + + operations = [ + migrations.CreateModel( + name='Funding', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('sort_order', models.IntegerField(blank=True, editable=False, null=True)), + ('value', models.PositiveIntegerField()), + ('year', models.PositiveIntegerField()), + ('duration', models.PositiveIntegerField(help_text='In months')), + ('page', modelcluster.fields.ParentalKey(on_delete=django.db.models.deletion.CASCADE, related_name='funding', to='people.PersonPage')), + ('source', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='wagtailcore.Page')), + ], + options={ + 'ordering': ['sort_order'], + 'abstract': False, + }, + ), + ] diff --git a/opentech/public/people/models.py b/opentech/public/people/models.py index 0534a032ec2055785e24883e739908b325ab2ff1..04ca3f7e421fe7380951e0e72634b90ed310f7b5 100644 --- a/opentech/public/people/models.py +++ b/opentech/public/people/models.py @@ -1,15 +1,19 @@ from django.db import models +from django.core.exceptions import ValidationError from django.utils.functional import cached_property from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator from django.conf import settings from modelcluster.fields import ParentalKey +from wagtail.wagtailcore.models import Orderable from wagtail.wagtailcore.fields import StreamField from wagtail.wagtailadmin.edit_handlers import ( FieldPanel, + FieldRowPanel, InlinePanel, MultiFieldPanel, + PageChooserPanel, StreamFieldPanel ) from wagtail.wagtailimages.edit_handlers import ImageChooserPanel @@ -25,7 +29,7 @@ class SocialMediaProfile(models.Model): ) site_titles = ( ('twitter', "Twitter"), - ('linkedin', "LinkedIn") + ('linkedin', "LinkedIn"), ) site_urls = ( ('twitter', 'https://twitter.com/'), @@ -68,14 +72,65 @@ class PersonPagePersonType(models.Model): return self.person_type.title -class PersonPagePhoneNumber(models.Model): - page = ParentalKey('PersonPage', related_name='phone_numbers') - phone_number = models.CharField(max_length=255) +class Funding(Orderable): + page = ParentalKey('PersonPage', related_name='funding') + value = models.PositiveIntegerField() + year = models.PositiveIntegerField() + duration = models.PositiveIntegerField(help_text='In months') + source = models.ForeignKey( + 'wagtailcore.Page', + on_delete=models.PROTECT, + ) + + panels = [ + FieldRowPanel([ + FieldPanel('year'), + FieldPanel('value'), + FieldPanel('duration'), + ]), + # This is stubbed as we need to be able to select from multiple + PageChooserPanel('source'), + ] + + +class PersonContactInfomation(Orderable): + methods = ( + ('irc', 'IRC'), + ('im_jabber_xmpp', 'IM/Jabber/XMPP'), + ('phone', 'Phone'), + ('pgp', 'PGP fingerprint'), + ('otr', 'OTR fingerprint'), + ) + page = ParentalKey('PersonPage', related_name='contact_details') + contact_method = models.CharField(max_length=255, choices=methods, blank=True) + other_method = models.CharField(max_length=255, blank=True, verbose_name='Other') + contact_detail = models.CharField(max_length=255) panels = [ - FieldPanel('phone_number') + FieldRowPanel([ + FieldPanel('contact_method'), + FieldPanel('other_method'), + ]), + FieldPanel('contact_detail'), ] + @property + def method_display(self): + return self.other_method or self.get_contact_method_display() + + def clean(self): + if not (self.contact_method or self.other_method): + raise ValidationError({ + 'contact_method': 'Please select or type at least one contact method.', + 'other_method': '', + }) + + if self.contact_method and self.other_method: + raise ValidationError({ + 'contact_method': 'Please only select or type one contact method.', + 'other_method': '', + }) + class PersonPage(BasePage): subpage_types = [] @@ -107,13 +162,18 @@ class PersonPage(BasePage): FieldPanel('website'), MultiFieldPanel([ FieldPanel('email'), - InlinePanel('phone_numbers', label='Phone numbers'), + InlinePanel('contact_details', label='Other Contact Methods'), ], heading='Contact information'), InlinePanel('person_types', label='Person types'), FieldPanel('introduction'), - StreamFieldPanel('biography') + StreamFieldPanel('biography'), + InlinePanel('funding', label='Funding'), ] + @property + def total_funding(self): + return sum(funding.value for funding in self.funding.all()) + class PersonIndexPage(BasePage): subpage_types = ['PersonPage'] diff --git a/opentech/public/people/templates/people/person_page.html b/opentech/public/people/templates/people/person_page.html index 8d860d7c92491d0a8e3f8da511e9259d3af60e0e..342ddc2c740fc513267e09c000db9509b17c6699 100644 --- a/opentech/public/people/templates/people/person_page.html +++ b/opentech/public/people/templates/people/person_page.html @@ -23,11 +23,11 @@ <p>{{ page.email }}</p> {% endif %} - {% with phone_numbers=page.phone_numbers.all %} - {% if phone_numbers %} + {% with contact_details=page.contact_details.all %} + {% if contact_details %} - {% for related_phone_number in phone_numbers %} - <p>{{ related_phone_number.phone_number }}</p> + {% for contact in contact_details %} + <p>{{ contact.method_display }}: {{ contact.contact_detail }}</p> {% endfor %} {% endif %} @@ -52,6 +52,18 @@ <h3>{{ item.get_service_display }}</h3> <p>{{ item.profile_url }}</p> {% endfor %} + <h2>Funding to date</h2> + {% for funding in page.funding.all %} + <table> + <tr> + <td>{{ funding.year }}</td> + <td>${{ funding.value }}</td> + <td>{{ funding.duration }} months</td> + <td><a href="{% pageurl funding.source %}">{{ funding.source }}</a></td> + </tr> + </table> + {% endfor %} + <p>Total Funding: {{ page.total_funding }}</p> </div> </section> diff --git a/opentech/public/utils/models.py b/opentech/public/utils/models.py index c284e259039e465988ccc69ab39367e0d545867d..08d72f3bbfe463094b0e4eb5ad085cfcf498578b 100644 --- a/opentech/public/utils/models.py +++ b/opentech/public/utils/models.py @@ -23,7 +23,7 @@ class LinkFields(models.Model): """ link_page = models.ForeignKey( - 'wagtailcore.Page', + 'wagtailcore.FieldPanelPage', blank=True, null=True, on_delete=models.SET_NULL