Commit e28cbe1c authored by njoyard's avatar njoyard
Browse files

Merge pull request #83 from political-memory/enhance-representative-details

Enhance representative details, fixes #74
parents 365ec31a 1054bba0
# coding: utf-8
from django import template
from django.utils.safestring import mark_safe
import re
register = template.Library()
link = '<a class="{network}-link" href="{url}" target="_blank">{label}</a>'
@register.filter
def twitter_link(url):
return mark_safe(link.format(network='twitter', url=url,
label=re.sub(r'.*/@?([^/]+)', '@\\1', re.sub(r'/$', '', url.strip()))))
@register.filter
def facebook_link(url):
return mark_safe(link.format(network='facebook', url=url,
label=re.sub(r'.*/([^/]+)', '\\1', re.sub(r'/$', '', url.strip()))))
@register.filter
def website_link(url):
short_url = re.sub(r'^https?://([^/]+).*', '\\1', url)
return mark_safe(link.format(network='website', url=url,
label=short_url))
@register.filter
def email_link(address):
return mark_safe(link.format(network='email', url='mailto:%s' % address,
label=address))
......@@ -3,6 +3,7 @@
<table class='table table-condensed votes'>
<tr>
<th>Title</th>
<th>Date</th>
<th class='icon-cell'>
Memopol recommendation
</th>
......@@ -17,14 +18,15 @@
<tr>
<td>Stop acta !</td>
<td class='date-cell'>Nov.24,2010</td>
<td class='icon-cell'>
<i aria-label="for" class="fa fa-thumbs-up vote_positive" title="for" ></i>
</td>
<td class='icon-cell'>
<i aria-label="for" class="fa fa-thumbs-up vote_positive" title="for" ></i>
<i aria-label="against" class="fa fa-thumbs-down vote_negative" title="against" ></i>
</td>
<td class='icon-cell'>
<span class="label label-success">4</span>
<span class="label label-danger">-6</span>
</td>
......@@ -32,6 +34,7 @@
<tr>
<td>Stop acta !</td>
<td class='date-cell'>Nov.24,2010</td>
<td class='icon-cell'>
<i aria-label="for" class="fa fa-thumbs-up vote_positive" title="for" ></i>
</td>
......@@ -47,14 +50,15 @@
<tr>
<td>Stop acta !</td>
<td class='date-cell'>Nov.24,2010</td>
<td class='icon-cell'>
<i aria-label="for" class="fa fa-thumbs-up vote_positive" title="for" ></i>
</td>
<td class='icon-cell'>
<i aria-label="against" class="fa fa-thumbs-down vote_negative" title="against" ></i>
<i aria-label="for" class="fa fa-thumbs-up vote_positive" title="for" ></i>
</td>
<td class='icon-cell'>
<span class="label label-danger">-6</span>
<span class="label label-success">4</span>
</td>
......
......@@ -10,7 +10,7 @@
- The Political Memory of </title>
<link rel="stylesheet" href="/static/collected/libs/bootstrap/dist/css/bootstrap.min.css" type="text/css" /><link rel="stylesheet" href="/static/collected/libs/fontawesome/css/font-awesome.min.css" type="text/css" /><link rel="stylesheet" href="/static/collected/libs/flag-icon-css/css/flag-icon.min.css" type="text/css" /><link rel="stylesheet" href="/static/collected/CACHE/css/base.6aeeaa87703d.css" type="text/css" />
<link rel="stylesheet" href="/static/collected/libs/bootstrap/dist/css/bootstrap.min.css" type="text/css" /><link rel="stylesheet" href="/static/collected/libs/fontawesome/css/font-awesome.min.css" type="text/css" /><link rel="stylesheet" href="/static/collected/libs/flag-icon-css/css/flag-icon.min.css" type="text/css" /><link rel="stylesheet" href="/static/collected/CACHE/css/base.3c5ffeab3cbf.css" type="text/css" />
<script type="text/javascript" src="/static/collected/libs/jquery/dist/jquery.js"></script>
<script type="text/javascript" src="/static/collected/libs/bootstrap/dist/js/bootstrap.js"></script>
......
......@@ -10,7 +10,7 @@
- The Political Memory of </title>
<link rel="stylesheet" href="/static/collected/libs/bootstrap/dist/css/bootstrap.min.css" type="text/css" /><link rel="stylesheet" href="/static/collected/libs/fontawesome/css/font-awesome.min.css" type="text/css" /><link rel="stylesheet" href="/static/collected/libs/flag-icon-css/css/flag-icon.min.css" type="text/css" /><link rel="stylesheet" href="/static/collected/CACHE/css/base.6aeeaa87703d.css" type="text/css" />
<link rel="stylesheet" href="/static/collected/libs/bootstrap/dist/css/bootstrap.min.css" type="text/css" /><link rel="stylesheet" href="/static/collected/libs/fontawesome/css/font-awesome.min.css" type="text/css" /><link rel="stylesheet" href="/static/collected/libs/flag-icon-css/css/flag-icon.min.css" type="text/css" /><link rel="stylesheet" href="/static/collected/CACHE/css/base.3c5ffeab3cbf.css" type="text/css" />
<script type="text/javascript" src="/static/collected/libs/jquery/dist/jquery.js"></script>
<script type="text/javascript" src="/static/collected/libs/bootstrap/dist/js/bootstrap.js"></script>
......
......@@ -10,7 +10,7 @@
- The Political Memory of </title>
<link rel="stylesheet" href="/static/collected/libs/bootstrap/dist/css/bootstrap.min.css" type="text/css" /><link rel="stylesheet" href="/static/collected/libs/fontawesome/css/font-awesome.min.css" type="text/css" /><link rel="stylesheet" href="/static/collected/libs/flag-icon-css/css/flag-icon.min.css" type="text/css" /><link rel="stylesheet" href="/static/collected/CACHE/css/base.6aeeaa87703d.css" type="text/css" />
<link rel="stylesheet" href="/static/collected/libs/bootstrap/dist/css/bootstrap.min.css" type="text/css" /><link rel="stylesheet" href="/static/collected/libs/fontawesome/css/font-awesome.min.css" type="text/css" /><link rel="stylesheet" href="/static/collected/libs/flag-icon-css/css/flag-icon.min.css" type="text/css" /><link rel="stylesheet" href="/static/collected/CACHE/css/base.3c5ffeab3cbf.css" type="text/css" />
<script type="text/javascript" src="/static/collected/libs/jquery/dist/jquery.js"></script>
<script type="text/javascript" src="/static/collected/libs/bootstrap/dist/js/bootstrap.js"></script>
......
......@@ -10,7 +10,7 @@
- The Political Memory of </title>
<link rel="stylesheet" href="/static/collected/libs/bootstrap/dist/css/bootstrap.min.css" type="text/css" /><link rel="stylesheet" href="/static/collected/libs/fontawesome/css/font-awesome.min.css" type="text/css" /><link rel="stylesheet" href="/static/collected/libs/flag-icon-css/css/flag-icon.min.css" type="text/css" /><link rel="stylesheet" href="/static/collected/CACHE/css/base.6aeeaa87703d.css" type="text/css" />
<link rel="stylesheet" href="/static/collected/libs/bootstrap/dist/css/bootstrap.min.css" type="text/css" /><link rel="stylesheet" href="/static/collected/libs/fontawesome/css/font-awesome.min.css" type="text/css" /><link rel="stylesheet" href="/static/collected/libs/flag-icon-css/css/flag-icon.min.css" type="text/css" /><link rel="stylesheet" href="/static/collected/CACHE/css/base.3c5ffeab3cbf.css" type="text/css" />
<script type="text/javascript" src="/static/collected/libs/jquery/dist/jquery.js"></script>
<script type="text/javascript" src="/static/collected/libs/bootstrap/dist/js/bootstrap.js"></script>
......
......@@ -10,7 +10,7 @@
- The Political Memory of </title>
<link rel="stylesheet" href="/static/collected/libs/bootstrap/dist/css/bootstrap.min.css" type="text/css" /><link rel="stylesheet" href="/static/collected/libs/fontawesome/css/font-awesome.min.css" type="text/css" /><link rel="stylesheet" href="/static/collected/libs/flag-icon-css/css/flag-icon.min.css" type="text/css" /><link rel="stylesheet" href="/static/collected/CACHE/css/base.6aeeaa87703d.css" type="text/css" />
<link rel="stylesheet" href="/static/collected/libs/bootstrap/dist/css/bootstrap.min.css" type="text/css" /><link rel="stylesheet" href="/static/collected/libs/fontawesome/css/font-awesome.min.css" type="text/css" /><link rel="stylesheet" href="/static/collected/libs/flag-icon-css/css/flag-icon.min.css" type="text/css" /><link rel="stylesheet" href="/static/collected/CACHE/css/base.3c5ffeab3cbf.css" type="text/css" />
<script type="text/javascript" src="/static/collected/libs/jquery/dist/jquery.js"></script>
<script type="text/javascript" src="/static/collected/libs/bootstrap/dist/js/bootstrap.js"></script>
......
......@@ -12,9 +12,13 @@ class RepresentativeDetailTest(UrlGetTestMixin, TestCase):
# Ensure one-time cached queries occur before the actual test
self.client.get(self.url)
with self.assertNumQueries(5):
with self.assertNumQueries(10):
"""
- One query for the rep details and foreign key (profile)
- One query for reverse relation on phones
- One query for reverse relation on addresses
- One query for reverse relation on emails
- Two queries for reverse relation on websites (social and other)
- One query for reverse relation on votes
- One query for reverse relation on mandates
- One query for reverse relation positions
......
......@@ -3,7 +3,7 @@ from django.db import models
from core.views import GridListMixin, PaginationMixin, CSVDownloadMixin
from representatives import views as representatives_views
from representatives.models import Representative
from representatives.models import (Representative, Address, Phone, WebSite)
from representatives_votes import views as representatives_votes_views
from representatives_votes.models import Dossier, Proposal
from representatives_positions.forms import PositionForm
......@@ -41,11 +41,35 @@ class RepresentativeDetail(representatives_views.RepresentativeDetail):
queryset = Representative.objects.select_related('score')
def get_queryset(self):
qs = super(RepresentativeDetail, self).get_queryset()
votes = VoteScore.objects.filter(
proposal__in=Proposal.objects.exclude(recommendation=None),
).select_related('proposal__recommendation')
qs = qs.prefetch_related(models.Prefetch('votes', queryset=votes))
social = ['twitter', 'facebook']
qs = super(RepresentativeDetail, self).get_queryset().prefetch_related(
'email_set',
models.Prefetch(
'website_set',
queryset=WebSite.objects.filter(kind__in=social),
to_attr='social_websites'
),
models.Prefetch(
'website_set',
queryset=WebSite.objects.exclude(kind__in=social),
to_attr='other_websites'
),
models.Prefetch(
'address_set',
queryset=Address.objects.select_related('country')
),
models.Prefetch(
'phone_set',
queryset=Phone.objects.select_related('address__country')
),
models.Prefetch(
'votes',
queryset=VoteScore.objects.filter(
proposal__in=Proposal.objects.exclude(recommendation=None),
).select_related('proposal__recommendation').order_by(
'-proposal__datetime')
)
)
return qs
def get_context_data(self, **kwargs):
......@@ -53,6 +77,7 @@ class RepresentativeDetail(representatives_views.RepresentativeDetail):
c['position_form'] = PositionForm(
initial={'representative': self.object.pk})
self.add_representative_country_and_main_mandate(c['object'])
return c
......
......@@ -7,6 +7,7 @@
@import 'positions';
@import 'chambers';
@import 'groups';
@import 'external';
body {
background: #E5E5E5;
......
a.twitter-link:before,
a.facebook-link:before {
content: ' ';
overflow: hidden;
display: inline-block;
width: 1.5em;
height: 1.5em;
vertical-align: bottom;
}
a.twitter-link:before {
background-size: 110%;
background-position: center;
background-image: url(../images/twitter.png);
}
a.facebook-link:before {
background-size: 75%;
background-repeat: no-repeat;
background-position: center;
background-image: url(../images/facebook.png);
}
\ No newline at end of file
......@@ -36,6 +36,10 @@
color: #333;
}
.date-cell {
white-space: nowrap;
}
.representative_grid {
display: flex;
flex-wrap: wrap;
......
.address
- if address.floor and address.office_number
.office Floor {{ address.floor }} - office {{ address.office_number }}
.street {{ address.number }} {{ address.street }}
.city {{ address.city }} {{ address.postcode }}, {{ address.country.name }}
- load memopol_tags
- load representatives_tags
- load representatives_recommendations_tags
- load humanize
......@@ -39,3 +40,20 @@
Born in {{ representative.birth_place }} the
{{ representative.birth_date|naturalday:'d/m/Y' }}
({{ representative.get_gender_display }})
- if representative.social_websites|length > 0
%tr
%th Social
%td
- for site in representative.social_websites
- if site.kind == 'twitter'
= site.url|twitter_link
- elif site.kind == 'facebook'
= site.url|facebook_link
- if representative.other_websites|length > 0
%tr
%th Websites
%td
- for site in representative.other_websites
= site.url|website_link
- load memopol_tags
.row.representative-contact
.col-md-12
%h2 Contact information
%table.table.table-condensed.detail-view
- for email in representative.email_set.all
%tr
%th E-mail
%td
= email.email|email_link
- if representative.phone_set.all|length > 0
%tr
%th Phone numbers
%td
- for phone in representative.phone_set.all
.phone {{ phone.number }}
- for address in representative.address_set.all
%tr
%th
= address.name
%td
- include 'representatives/_address_block.html' with address=address
......@@ -12,6 +12,7 @@
.row
.col-md-6
- include 'representatives/_representative_block.html' with representative=representative
- include 'representatives/_representative_contact.html' with representative=representative
.col-md-6
%h2#votes Votes
......@@ -19,6 +20,7 @@
%table.table.table-condensed.votes
%tr
%th Title
%th Date
%th.icon-cell
Memopol recommendation
%th.icon-cell
......@@ -29,6 +31,8 @@
- for vote in votes
%tr
%td= vote.proposal.recommendation.title
%td.date-cell
= vote.proposal.datetime|date:'N j, Y'
%td.icon-cell
= vote.proposal.recommendation.recommendation|position_icon
%td.icon-cell
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment