Commit 27d3dfe5 authored by Arnaud Fabre's avatar Arnaud Fabre

Design improvements

Adds-flag icons
Adds fluid containers
Adds a memopolVote proxy model
parent 4ecd390c
...@@ -2,7 +2,8 @@ ...@@ -2,7 +2,8 @@
"name": "Memopol", "name": "Memopol",
"version": "3.0.0", "version": "3.0.0",
"dependencies": { "dependencies": {
"bootstrap": "~3.3.5" "bootstrap": "~3.3.5",
"flag-icon-css": "~0.7.1"
}, },
"devDependencies": { "devDependencies": {
"fontawesome": "~4.3.0" "fontawesome": "~4.3.0"
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
</head> </head>
<body {% block bodyattrs %}{% endblock %}> <body {% block bodyattrs %}{% endblock %}>
{% include "core/blocks/header.html" %} {% include "core/blocks/header.html" %}
<div class="container main-container"> <div class="container-fluid main-container">
{% block content %} {% block content %}
{% endblock %} {% endblock %}
</div> </div>
......
- load i18n - load i18n
#footer.container #footer.container-fluid
- blocktrans - blocktrans
Memopol is free software Memopol is free software
<a href="https://gitorious.org/memopol2-0">released</a> <a href="https://gitorious.org/memopol2-0">released</a>
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
- load cache - load cache
- load staticfiles - load staticfiles
#header.container #header.container-fluid
%a{href: "/", id: 'logo'} %a{href: "/", id: 'logo'}
%img{src: '{% static "images/logo.png" %}'} %img{src: '{% static "images/logo.png" %}'}
%h1 %h1
...@@ -12,6 +12,5 @@ ...@@ -12,6 +12,5 @@
%p.organization %p.organization
=config.ORGANIZATION_NAME =config.ORGANIZATION_NAME
#nav.container #nav.container-fluid
-include "core/blocks/navigation.html" -include "core/blocks/navigation.html"
...@@ -24,10 +24,10 @@ from django.db import models ...@@ -24,10 +24,10 @@ from django.db import models
from django.core.exceptions import ObjectDoesNotExist from django.core.exceptions import ObjectDoesNotExist
from django.db.models.signals import post_save from django.db.models.signals import post_save
from django.dispatch import receiver from django.dispatch import receiver
from django.utils.functional import cached_property # from django.utils.functional import cached_property
from representatives.models import Representative, Mandate, Country from representatives.models import Representative, Mandate, Country
from representatives_votes.models import Vote from votes.models import MemopolVote
from core.utils import create_child_instance_from_parent from core.utils import create_child_instance_from_parent
...@@ -39,21 +39,7 @@ class MemopolRepresentative(Representative): ...@@ -39,21 +39,7 @@ class MemopolRepresentative(Representative):
def update_score(self): def update_score(self):
score = 0 score = 0
for vote in self.votes.all(): for vote in self.votes.all():
proposal = vote.proposal score += vote.absolute_score
try:
if proposal.recommendation:
recommendation = proposal.recommendation
if ( vote.position != recommendation.recommendation
and (
vote.position == 'abstain' or
recommendation.recommendation == 'abstain' )):
score -= (recommendation.weight / 2)
elif vote.position != recommendation.recommendation:
score -= recommendation.weight
else:
score += recommendation.weight
except Exception:
pass
self.score = score self.score = score
self.save() self.save()
...@@ -102,10 +88,10 @@ class MemopolRepresentative(Representative): ...@@ -102,10 +88,10 @@ class MemopolRepresentative(Representative):
) )
def votes_with_proposal(self): def votes_with_proposal(self):
return self.votes.select_related( return MemopolVote.objects.select_related(
'proposal', 'proposal',
'proposal__recommendation' 'proposal__recommendation'
) ).filter(representative=self)
@receiver(post_save, sender=Representative) @receiver(post_save, sender=Representative)
......
- load by_group_url - load representatives_extras
.representative .representative
...@@ -15,12 +15,11 @@ ...@@ -15,12 +15,11 @@
%tr.score %tr.score
%th Score %th Score
%td %td
%span.label.label-success = representative.score|score_label
%a{:href => '#votes'}
= representative.score
%tr %tr
%th Country %th Country
%td= representative.country.name %td
= representative.country|country_flag
%tr %tr
%th Party %th Party
%td %td
......
...@@ -3,29 +3,38 @@ ...@@ -3,29 +3,38 @@
- extends 'base.html' - extends 'base.html'
- load humanize - load humanize
- load by_group_url - load representatives_extras
- load bootstrap3 - load bootstrap3
- block head - block head
{{ position_form.media }} {{ position_form.media }}
- block content - block content
- include 'legislature/blocks/representative_header.html' with representative=representative .row
.col-md-6
- include 'legislature/blocks/representative_block.html' with representative=representative
.col-md-6
%h2#votes Votes %h2#votes Votes
%table.table.table-condensed.votes %table.table.table-condensed.votes
%tr %tr
%th Title %th Title
%th Position %th.icon-cell
%th Recommendation Memopol recommendation
%th Score %th.icon-cell
Representative vote
%th.icon-cell
Score
- for vote in representative.votes_with_proposal.all - for vote in representative.votes_with_proposal.all
%tr %tr
%td= vote.proposal.recommendation.title %td= vote.proposal.recommendation.title
%td= vote.position %td.icon-cell
%td= vote.proposal.recommendation.recommendation = vote.proposal.recommendation.recommendation|position_icon
%td= vote.proposal.recommendation.weight %td.icon-cell
= vote.position|position_icon
%td.icon-cell
= vote.absolute_score|score_label
%h2 Mandates %h2 Mandates
......
- extends 'base.html' - extends 'base.html'
- load by_group_url - load representatives_extras
- block content - block content
...@@ -27,16 +27,16 @@ ...@@ -27,16 +27,16 @@
%td %td
%a{'href': "{% url 'legislature:representative-detail' name=representative.slug %}"} %a{'href': "{% url 'legislature:representative-detail' name=representative.slug %}"}
={representative.full_name} = representative.full_name
%td %td
%a{'href': "{% url 'legislature:representative-index' group_kind='country' group=representative.country.code %}"} %a{'href': "{% url 'legislature:representative-index' group_kind='country' group=representative.country.code %}"}
={representative.country.name} = representative.country|country_flag
%td %td
%a{'href': "{{ representative.main_mandate|by_group_url }}"} %a{'href': "{{ representative.main_mandate|by_group_url }}"}
={representative.main_mandate.group.abbreviation} = representative.main_mandate.group.abbreviation
%td %td
={representative.score} = representative.score|score_label
- include "core/blocks/pagination.html" - include "core/blocks/pagination.html"
from django import template
from django.core.urlresolvers import reverse
from django.utils.safestring import mark_safe
from representatives.models import Mandate, Group
register = template.Library()
@register.filter
def position_icon(position):
if position == 'for':
return mark_safe(
'<i \
aria-label="for" \
class="fa fa-thumbs-up vote_positive" \
title="for" \
></i>')
elif position == 'against':
return mark_safe(
'<i \
aria-label="against" \
class="fa fa-thumbs-down vote_negative" \
title="against" \
></i>')
else:
return mark_safe(
'<i \
aria-label="abstain" \
class="fa fa-circle-o vote_abstain" \
title="abstain" \
></i>')
@register.filter
def score_label(score):
if score > 0:
return mark_safe('<span class="label label-success">{}</span>'.format(score))
elif score < 0:
return mark_safe('<span class="label label-danger">{}</span>'.format(score))
else:
return mark_safe('<span class="label label-default">{}</span>'.format(score))
@register.filter
def country_flag(country):
return mark_safe('{} <span class="flag-icon flag-icon-{}"></span>'.format(
country.name,
country.code.lower()
))
@register.filter
def by_group_url(group):
if isinstance(group, Mandate):
group = group.group
if not isinstance(group, Group):
return ''
kwargs = {'group_kind': group.kind}
if group.abbreviation:
kwargs['group'] = group.abbreviation
else:
kwargs['group'] = group.name
# kwargs['group_id'] = group.id
return reverse(
'legislature:representative-index',
kwargs=kwargs
)
...@@ -10,7 +10,7 @@ body { ...@@ -10,7 +10,7 @@ body {
background: #E5E5E5; background: #E5E5E5;
} }
.container { .container, .container-fluid {
background: white; background: white;
} }
......
...@@ -23,3 +23,15 @@ ...@@ -23,3 +23,15 @@
width: 50%; width: 50%;
margin: auto; margin: auto;
} }
.vote_negative {
color: red;
}
.vote_positive {
color: green;
}
.vote_abstain {
color: #333;
}
\ No newline at end of file
@import '../libs/bootstrap/less/bootstrap'; @import '../libs/bootstrap/less/bootstrap';
@import '../libs/fontawesome/less/font-awesome'; @import '../libs/fontawesome/less/font-awesome';
// Flag icons
@import '../libs/flag-icon-css/less/variabless';
@flag-icon-css-path: '../libs/flag-icon-css/flags';
@import '../libs/flag-icon-css/less/flag-icon-base';
@import '../libs/flag-icon-css/less/flag-icon-list';
...@@ -7,6 +7,10 @@ table.detail-view { ...@@ -7,6 +7,10 @@ table.detail-view {
text-align: right; text-align: right;
} }
th:after{ th:after{
content: ' :'; content: ' :';
} }
} }
.icon-cell {
text-align: center;
}
\ No newline at end of file
...@@ -79,7 +79,10 @@ table.detail-view th { ...@@ -79,7 +79,10 @@ table.detail-view th {
text-align: right; text-align: right;
} }
table.detail-view th:after { table.detail-view th:after {
content: ' :'; content: ' :';
}
.icon-cell {
text-align: center;
} }
.representative h1 { .representative h1 {
text-align: center; text-align: center;
...@@ -100,6 +103,15 @@ table.detail-view th:after { ...@@ -100,6 +103,15 @@ table.detail-view th:after {
width: 50%; width: 50%;
margin: auto; margin: auto;
} }
.vote_negative {
color: red;
}
.vote_positive {
color: green;
}
.vote_abstain {
color: #333;
}
.quote { .quote {
width: 70%; width: 70%;
margin: auto; margin: auto;
...@@ -123,7 +135,8 @@ table.detail-view th:after { ...@@ -123,7 +135,8 @@ table.detail-view th:after {
body { body {
background: #E5E5E5; background: #E5E5E5;
} }
.container { .container,
.container-fluid {
background: white; background: white;
} }
.main-container { .main-container {
......
...@@ -8567,3 +8567,1517 @@ button.close { ...@@ -8567,3 +8567,1517 @@ button.close {
.fa-medium:before { .fa-medium:before {
content: "\f23a"; content: "\f23a";
} }
.flag-icon-background {
background-size: contain;
background-position: 50%;
background-repeat: no-repeat;
}
.flag-icon {
background-size: contain;
background-position: 50%;
background-repeat: no-repeat;
position: relative;
display: inline-block;
width: 1.33333333em;
line-height: 1em;
}
.flag-icon:before {
content: "\00a0";
}
.flag-icon.flag-icon-squared {
width: 1em;
}
.flag-icon-ad {
background-image: url(../libs/flag-icon-css/flags/4x3/ad.svg);
}
.flag-icon-ad.flag-icon-squared {
background-image: url(../libs/flag-icon-css/flags/1x1/ad.svg);
}
.flag-icon-ae {
background-image: url(../libs/flag-icon-css/flags/4x3/ae.svg);
}
.flag-icon-ae.flag-icon-squared {
background-image: url(../libs/flag-icon-css/flags/1x1/ae.svg);
}
.flag-icon-af {
background-image: url(../libs/flag-icon-css/flags/4x3/af.svg);
}
.flag-icon-af.flag-icon-squared {
background-image: url(../libs/flag-icon-css/flags/1x1/af.svg);
}
.flag-icon-ag {
background-image: url(../libs/flag-icon-css/flags/4x3/ag.svg);
}
.flag-icon-ag.flag-icon-squared {
background-image: url(../libs/flag-icon-css/flags/1x1/ag.svg);
}
.flag-icon-ai {
background-image: url(../libs/flag-icon-css/flags/4x3/ai.svg);
}
.flag-icon-ai.flag-icon-squared {
background-image: url(../libs/flag-icon-css/flags/1x1/ai.svg);
}
.flag-icon-al {
background-image: url(../libs/flag-icon-css/flags/4x3/al.svg);
}
.flag-icon-al.flag-icon-squared {
background-image: url(../libs/flag-icon-css/flags/1x1/al.svg);
}
.flag-icon-am {
background-image: url(../libs/flag-icon-css/flags/4x3/am.svg);
}
.flag-icon-am.flag-icon-squared {
background-image: url(../libs/flag-icon-css/flags/1x1/am.svg);
}
.flag-icon-ao {
background-image: url(../libs/flag-icon-css/flags/4x3/ao.svg);
}
.flag-icon-ao.flag-icon-squared {
background-image: url(../libs/flag-icon-css/flags/1x1/ao.svg);
}
.flag-icon-aq {
background-image: url(../libs/flag-icon-css/flags/4x3/aq.svg);
}
.flag-icon-aq.flag-icon-squared {
background-image: url(../libs/flag-icon-css/flags/1x1/aq.svg);
}
.flag-icon-ar {
background-image: url(../libs/flag-icon-css/flags/4x3/ar.svg);
}
.flag-icon-ar.flag-icon-squared {
background-image: url(../libs/flag-icon-css/flags/1x1/ar.svg);
}
.flag-icon-as {
background-image: url(../libs/flag-icon-css/flags/4x3/as.svg);
}
.flag-icon-as.flag-icon-squared {
background-image: url(../libs/flag-icon-css/flags/1x1/as.svg);
}
.flag-icon-at {
background-image: url(../libs/flag-icon-css/flags/4x3/at.svg);
}
.flag-icon-at.flag-icon-squared {
background-image: url(../libs/flag-icon-css/flags/1x1/at.svg);
}
.flag-icon-au {
background-image: url(../libs/flag-icon-css/flags/4x3/au.svg);
}
.flag-icon-au.flag-icon-squared {
background-image: url(../libs/flag-icon-css/flags/1x1/au.svg);
}
.flag-icon-aw {
background-image: url(../libs/flag-icon-css/flags/4x3/aw.svg);
}
.flag-icon-aw.flag-icon-squared {
background-image: url(../libs/flag-icon-css/flags/1x1/aw.svg);
}
.flag-icon-ax {
background-image: url(../libs/flag-icon-css/flags/4x3/ax.svg);
}
.flag-icon-ax.flag-icon-squared {
background-image: url(../libs/flag-icon-css/flags/1x1/ax.svg);
}
.flag-icon-az {
background-image: url(../libs/flag-icon-css/flags/4x3/az.svg);
}
.flag-icon-az.flag-icon-squared {
background-image: url(../libs/flag-icon-css/flags/1x1/az.svg);
}
.flag-icon-ba {
background-image: url(../libs/flag-icon-css/flags/4x3/ba.svg);
}
.flag-icon-ba.flag-icon-squared {
background-image: url(../libs/flag-icon-css/flags/1x1/ba.svg);
}
.flag-icon-bb {
background-image: url(../libs/flag-icon-css/flags/4x3/bb.svg);
}
.flag-icon-bb.flag-icon-squared {
background-image: url(../libs/flag-icon-css/flags/1x1/bb.svg);
}
.flag-icon-bd {
background-image: url(../libs/flag-icon-css/flags/4x3/bd.svg);
}
.flag-icon-bd.flag-icon-squared {
background-image: url(../libs/flag-icon-css/flags/1x1/bd.svg);
}
.flag-icon-be {
background-image: url(../libs/flag-icon-css/flags/4x3/be.svg);
}
.flag-icon-be.flag-icon-squared {
background-image: url(../libs/flag-icon-css/flags/1x1/be.svg);
}
.flag-icon-bf {
background-image: url(../libs/flag-icon-css/flags/4x3/bf.svg);
}
.flag-icon-bf.flag-icon-squared {
background-image: url(../libs/flag-icon-css/flags/1x1/bf.svg);
}
.flag-icon-bg {
background-image: url(../libs/flag-icon-css/flags/4x3/bg.svg);
}
.flag-icon-bg.flag-icon-squared {
background-image: url(../libs/flag-icon-css/flags/1x1/bg.svg);
}
.flag-icon-bh {
background-image: url(../libs/flag-icon-css/flags/4x3/bh.svg);
}
.flag-icon-bh.flag-icon-squared {
background-image: url(../libs/flag-icon-css/flags/1x1/bh.svg);
}
.flag-icon-bi {
background-image: url(../libs/flag-icon-css/flags/4x3/bi.svg);
}
.flag-icon-bi.flag-icon-squared {
background-image: url(../libs/flag-icon-css/flags/1x1/bi.svg);
}
.flag-icon-bj {
background-image: url(../libs/flag-icon-css/flags/4x3/bj.svg);
}
.flag-icon-bj.flag-icon-squared {
background-image: url(../libs/flag-icon-css/flags/1x1/bj.svg);
}
.flag-icon-bl {
background-image: url(../libs/flag-icon-css/flags/4x3/bl.svg);
}
.flag-icon-bl.flag-icon-squared {
background-image: url(../libs/flag-icon-css/flags/1x1/bl.svg);
}
.flag-icon-bm {
background-image: url(../libs/flag-icon-css/flags/4x3/bm.svg);
}
.flag-icon-bm.flag-icon-squared {
background-image: url(../libs/flag-icon-css/flags/1x1/bm.svg);
}
.flag-icon-bn {
background-image: url(../libs/flag-icon-css/flags/4x3/bn.svg);
}
.flag-icon-bn.flag-icon-squared {
background-image: url(../libs/flag-icon-css/flags/1x1/bn.svg);
}
.flag-icon-bo {
background-image: url(../libs/flag-icon-css/flags/4x3/bo.svg);
}
.flag-icon-bo.flag-icon-squared {
background-image: url(../libs/flag-icon-css/flags/1x1/bo.svg);
}
.flag-icon-bq {
background-image: url(../libs/flag-icon-css/flags/4x3/bq.svg);
}