Skip to content

Commit 02fcef7

Browse files
committed
First steps towards bios and photos in the tracker
- Legacy-Id: 11247
1 parent caf3a4c commit 02fcef7

12 files changed

Lines changed: 290 additions & 9 deletions

File tree

ietf/group/urls_info.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,6 @@
1919
(r'^bofs/$', views.bofs),
2020
(r'^email-aliases/$', 'ietf.group.views.email_aliases'),
2121
(r'^bofs/create/$', views_edit.edit, {'action': "create"}, "bof_create"),
22+
(r'^chair-photos/$', views.chair_photos),
2223
(r'^(?P<acronym>[a-zA-Z0-9-._]+)/', include('ietf.group.urls_info_details')),
2324
)

ietf/group/views.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -870,3 +870,12 @@ def derived_archives(request, acronym=None, group_type=None):
870870
'group':group,
871871
'list_acronym':list_acronym,
872872
}))
873+
874+
def chair_photos(request, group_type=None):
875+
if not group_type=='wg':
876+
raise Http404
877+
chair_roles = sorted(Role.objects.filter(group__type='wg',group__state='active',name_id='chair'),key=lambda x: x.person.last_name()+x.person.name+x.group.acronym)
878+
for role in chair_roles:
879+
role.last_initial = role.person.last_name()[0]
880+
return render(request, 'group/chair_photos.html', {'chair_roles':chair_roles})
881+

ietf/nomcom/models.py

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
from django.db import models
55
from django.db.models.signals import post_delete
66
from django.conf import settings
7-
from django.core.files.storage import FileSystemStorage
87
from django.contrib.auth.models import User
98
from django.template.loader import render_to_string
109
from django.template.defaultfilters import linebreaks
@@ -22,6 +21,8 @@
2221
initialize_requirements_for_position,
2322
delete_nomcom_templates)
2423

24+
from ietf.utils.storage import NoLocationMigrationFileSystemStorage
25+
2526

2627
def upload_path_handler(instance, filename):
2728
return os.path.join(instance.group.acronym, 'public.cert')
@@ -32,14 +33,6 @@ class ReminderDates(models.Model):
3233
nomcom = models.ForeignKey('NomCom')
3334

3435

35-
class NoLocationMigrationFileSystemStorage(FileSystemStorage):
36-
37-
def deconstruct(obj):
38-
path, args, kwargs = FileSystemStorage.deconstruct(obj)
39-
kwargs["location"] = None
40-
return (path, args, kwargs)
41-
42-
4336
class NomCom(models.Model):
4437
public_key = models.FileField(storage=NoLocationMigrationFileSystemStorage(location=settings.NOMCOM_PUBLIC_KEYS_DIR),
4538
upload_to=upload_path_handler, blank=True, null=True)
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# -*- coding: utf-8 -*-
2+
from __future__ import unicode_literals
3+
4+
from django.db import models, migrations
5+
6+
7+
class Migration(migrations.Migration):
8+
9+
dependencies = [
10+
('person', '0007_auto_20160520_0304'),
11+
]
12+
13+
operations = [
14+
migrations.AddField(
15+
model_name='person',
16+
name='biography',
17+
field=models.TextField(help_text=b'Short biography for use on leadership pages.', blank=True),
18+
preserve_default=True,
19+
),
20+
migrations.AddField(
21+
model_name='personhistory',
22+
name='biography',
23+
field=models.TextField(help_text=b'Short biography for use on leadership pages.', blank=True),
24+
preserve_default=True,
25+
),
26+
]

ietf/person/migrations/0009_populate_biography.py

Lines changed: 82 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# -*- coding: utf-8 -*-
2+
from __future__ import unicode_literals
3+
4+
from django.db import models, migrations
5+
import ietf.utils.storage
6+
7+
8+
class Migration(migrations.Migration):
9+
10+
dependencies = [
11+
('person', '0009_populate_biography'),
12+
]
13+
14+
operations = [
15+
migrations.AddField(
16+
model_name='person',
17+
name='photo',
18+
field=models.ImageField(storage=ietf.utils.storage.NoLocationMigrationFileSystemStorage(location=None), upload_to=b'photos/', blank=True),
19+
preserve_default=True,
20+
),
21+
migrations.AddField(
22+
model_name='person',
23+
name='photo_thumb',
24+
field=models.ImageField(storage=ietf.utils.storage.NoLocationMigrationFileSystemStorage(location=None), upload_to=b'photos/', blank=True),
25+
preserve_default=True,
26+
),
27+
migrations.AddField(
28+
model_name='personhistory',
29+
name='photo',
30+
field=models.ImageField(storage=ietf.utils.storage.NoLocationMigrationFileSystemStorage(location=None), upload_to=b'photos/', blank=True),
31+
preserve_default=True,
32+
),
33+
migrations.AddField(
34+
model_name='personhistory',
35+
name='photo_thumb',
36+
field=models.ImageField(storage=ietf.utils.storage.NoLocationMigrationFileSystemStorage(location=None), upload_to=b'photos/', blank=True),
37+
preserve_default=True,
38+
),
39+
]
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# -*- coding: utf-8 -*-
2+
from __future__ import unicode_literals
3+
4+
import os
5+
6+
from hashids import Hashids
7+
8+
from django.db import migrations
9+
from django.conf import settings
10+
from django.utils.text import slugify
11+
12+
def photo_name(person,thumb=False):
13+
hasher = Hashids(salt='Person photo name salt',min_length=5)
14+
return '%s-%s%s' % ( slugify(person.ascii), hasher.encode(person.id), '-th' if thumb else '' )
15+
16+
def forward(apps,schema_editor):
17+
Person = apps.get_model('person','Person')
18+
images_dir = os.path.join(settings.PHOTOS_DIR,settings.PHOTO_URL_PREFIX)
19+
image_filenames = []
20+
for (dirpath, dirnames, filenames) in os.walk(images_dir):
21+
image_filenames.extend(filenames)
22+
break # Only interested in the files in the top directory
23+
image_basenames = [os.path.splitext(name)[0] for name in image_filenames]
24+
for person in Person.objects.all():
25+
dirty = False
26+
if photo_name(person,thumb=False) in image_basenames:
27+
person.photo = image_filenames[image_basenames.index(photo_name(person,thumb=False))]
28+
dirty = True
29+
if photo_name(person,thumb=True) in image_basenames:
30+
person.photo_thumb = image_filenames[image_basenames.index(photo_name(person,thumb=True))]
31+
dirty = True
32+
if dirty:
33+
person.save()
34+
35+
def reverse(apps, schema_editor):
36+
pass
37+
38+
class Migration(migrations.Migration):
39+
40+
dependencies = [
41+
('person', '0010_add_photo_fields'),
42+
]
43+
44+
operations = [
45+
migrations.RunPython(forward,reverse)
46+
]

ietf/person/models.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,19 @@
22

33
import datetime
44
from urlparse import urljoin
5+
from hashids import Hashids
56

67
from django.conf import settings
78

89
from django.db import models
910
from django.contrib.auth.models import User
1011
from django.template.loader import render_to_string
12+
from django.utils.text import slugify
13+
1114

1215
from ietf.person.name import name_parts, initials
1316
from ietf.utils.mail import send_mail_preformatted
17+
from ietf.utils.storage import NoLocationMigrationFileSystemStorage
1418

1519
class PersonInfo(models.Model):
1620
time = models.DateTimeField(default=datetime.datetime.now) # When this Person record entered the system
@@ -23,6 +27,9 @@ class PersonInfo(models.Model):
2327
ascii_short = models.CharField("Abbreviated Name (ASCII)", max_length=32, null=True, blank=True, help_text="Example: A. Nonymous. Fill in this with initials and surname only if taking the initials and surname of the ASCII name above produces an incorrect initials-only form. (Blank is OK).")
2428
affiliation = models.CharField(max_length=255, blank=True, help_text="Employer, university, sponsor, etc.")
2529
address = models.TextField(max_length=255, blank=True, help_text="Postal mailing address.")
30+
biography = models.TextField(blank=True, help_text="Short biography for use on leadership pages.")
31+
photo = models.ImageField(storage=NoLocationMigrationFileSystemStorage(location=settings.PHOTOS_DIR),upload_to=settings.PHOTO_URL_PREFIX,blank=True)
32+
photo_thumb = models.ImageField(storage=NoLocationMigrationFileSystemStorage(location=settings.PHOTOS_DIR),upload_to=settings.PHOTO_URL_PREFIX,blank=True)
2633

2734
def __unicode__(self):
2835
return self.plain_name()
@@ -84,6 +91,11 @@ def formatted_email(self):
8491
def full_name_as_key(self):
8592
# this is mostly a remnant from the old views, needed in the menu
8693
return self.plain_name().lower().replace(" ", ".")
94+
95+
def photo_name(self,thumb=False):
96+
hasher = Hashids(salt='Person photo name salt',min_length=5)
97+
return '%s-%s%s' % ( slugify(self.ascii), hasher.encode(self.id), '-th' if thumb else '' )
98+
8799
class Meta:
88100
abstract = True
89101

ietf/settings.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,8 @@
104104
IETF_ID_URL = MEDIA_URL + 'id/'
105105
IETF_ID_ARCHIVE_URL = MEDIA_URL + 'archive/id/'
106106

107+
PHOTOS_DIR = '/a/www/www6/'
108+
PHOTO_URL_PREFIX = 'photos/'
107109

108110
# Absolute path to the directory static files should be collected to.
109111
# Example: "/var/www/example.com/static/"
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
{% extends "base.html" %}
2+
{# Copyright The IETF Trust 2015, All Rights Reserved #}
3+
{% load origin staticfiles %}
4+
5+
{% block morecss %}
6+
.well { max-width: 150px;}
7+
{% endblock %}
8+
9+
{% block bodyAttrs %}data-spy="scroll" data-target="#affix"{% endblock %}
10+
11+
{% block title %}Chair Photos{% endblock %}
12+
13+
{% block content %}
14+
{% origin %}
15+
{% load ietf_filters %}
16+
17+
<h1>Chair Photos</h1>
18+
19+
{% regroup chair_roles by last_initial as alphabet_blocks %}
20+
<div class="col-md-11">
21+
{% for letter in alphabet_blocks %}
22+
<div class="row anchor-target" id="{{letter.grouper}}">
23+
<div class="panel panel-default">
24+
<div class="panel-heading">{{letter.grouper}}</div>
25+
<div class="panel-body">
26+
<ul class="list-inline">
27+
{% regroup letter.list by person as person_groups %}
28+
{% for person_with_groups in person_groups %}
29+
<li>
30+
<div class="well">
31+
{% if person_with_groups.grouper.photo_thumb %}
32+
<img width=100px src="{{person_with_groups.grouper.photo_thumb.url}}"/>
33+
{% endif %}
34+
{% if person_with_groups.grouper.photo %}
35+
<div><a href="{{person_with_groups.grouper.photo.url}}"><strong>{{person_with_groups.grouper.plain_name}}</strong></a></div>
36+
{% else %}
37+
<div><strong>{{person_with_groups.grouper.plain_name}}</strong></div>
38+
{% endif %}
39+
<div>
40+
{% for role in person_with_groups.list %}
41+
{{role.group.acronym}}
42+
{% endfor %}
43+
</div>
44+
</div>
45+
</li>
46+
{% endfor %}
47+
</ul>
48+
</div>
49+
</div>
50+
</div>
51+
{% endfor %}
52+
</div>
53+
54+
<div class="col-md-1 hidden-print bs-docs-sidebar" id="affix">
55+
<ul class="nav nav-pills nav-stacked small fixed" data-spy="affix">
56+
{% for letter in alphabet_blocks %}
57+
<li><a href="#{{letter.grouper}}">{{letter.grouper}}</a></li>
58+
{% endfor %}
59+
</ul>
60+
</div>
61+
62+
{% endblock %}

0 commit comments

Comments
 (0)