Commit 42661d96 authored by Nicolas Joyard's avatar Nicolas Joyard

Implement theme details

parent 66d8be6a
......@@ -51,3 +51,25 @@ class RepresentativeBaseTest(BaseTest):
with self.assertNumQueries(self.queries):
self.client.get(self.url)
class ThemeBaseTest(BaseTest):
tab = 'none'
base_url = '/theme/etat-durgence/%s/'
"""
Common queries plus:
- 1 for the theme
"""
queries = BaseTest.left_pane_queries + 1
@property
def url(self):
return self.base_url % self.tab
def do_query_test(self):
# First query to set session variables
self.client.get(self.url)
with self.assertNumQueries(self.queries):
self.client.get(self.url)
<div class="text-left" id="description">
La réponse sécuritaire n'est pas la solution.
</div>
\ No newline at end of file
{
"status_code": 200
}
\ No newline at end of file
<h1 class="text-center">Etat d'urgence</h1>
\ No newline at end of file
{
"status_code": 200
}
\ No newline at end of file
<tr class="dossier">
<td>
<span class="chamber-icon" style="background-image: url(/static/collected/images/chamber-an.png)" title="Assemblée nationale"></span>
<span class="chamber-icon" style="background-image: url(/static/collected/images/chamber-sen.png)" title="Sénat"></span>
</td>
<td>
<a href="/votes/dossier/15407/">
Pouvoirs publics : prorogation de l'état d'urgence
</a>
</td>
<td>14/prorogation_loi_55-385</td>
</tr>
---
<tr class="dossier">
<td>
<span class="chamber-icon" style="background-image: url(/static/collected/images/chamber-an.png)" title="Assemblée nationale"></span>
</td>
<td>
<a href="/votes/dossier/15409/">
Pouvoirs publics : prorogation de l'application de la loi sur l'état d'urgence
</a>
</td>
<td>14/loi_55-385_prorogation_application</td>
</tr>
---
<tr class="dossier">
<td>
<span class="chamber-icon" style="background-image: url(/static/collected/images/chamber-an.png)" title="Assemblée nationale"></span>
<span class="chamber-icon" style="background-image: url(/static/collected/images/chamber-sen.png)" title="Sénat"></span>
</td>
<td>
<a href="/votes/dossier/15424/">
Pouvoirs publics : application de la loi relative à l’état d’urgence
</a>
</td>
<td>14/prorogation_application_loi_55-385</td>
</tr>
---
<tr class="dossier">
<td>
<span class="chamber-icon" style="background-image: url(/static/collected/images/chamber-an.png)" title="Assemblée nationale"></span>
<span class="chamber-icon" style="background-image: url(/static/collected/images/chamber-sen.png)" title="Sénat"></span>
</td>
<td>
<a href="/votes/dossier/15426/">
Pouvoirs publics : prorogation de l'application de la loi relative à l'état d'urgence
</a>
</td>
<td>14/application_loi_55-385_prorogation</td>
</tr>
\ No newline at end of file
{
"status_code": 200
}
\ No newline at end of file
<tr class="link">
<td>
<a class="external" href="https://www.laquadrature.net/fr/encore-une-fois" target="_blank">
CP LQDN : Etat d'urgence - encore une fois
</a>
</td>
<td>July 18, 2016</td>
</tr>
---
<tr class="link">
<td>
<a class="external" href="https://www.laquadrature.net/fr/etat-d-urgence-surenchere-dans-la-surveillance-de-masse" target="_blank">
CP LQDN: Etat d'urgence - surenchère dans la surveillance de masse
</a>
</td>
<td>July 21, 2016</td>
</tr>
\ No newline at end of file
{
"status_code": 200
}
\ No newline at end of file
from .base import ThemeBaseTest
class ThemeDetailTest(ThemeBaseTest):
def test_queries(self):
self.do_query_test()
def test_name(self):
return self.selector_test('#theme-detail h1')
def test_description(self):
return self.selector_test('#theme-detail #description')
from .base import ThemeBaseTest
class ThemeDossiersTest(ThemeBaseTest):
tab = 'dossiers'
"""
Theme base queries plus
- 1 for dossiers
- 1 for related documents
- 1 for related documents/chambers
"""
queries = ThemeBaseTest.queries + 3
def test_queries(self):
self.do_query_test()
def test_dossiers(self):
self.selector_test('.dossier')
from .base import ThemeBaseTest
class ThemeLinksTest(ThemeBaseTest):
tab = 'links'
"""
Theme base queries plus
- 1 for links
"""
queries = ThemeBaseTest.queries + 1
def test_queries(self):
self.do_query_test()
def test_links(self):
self.selector_test('.link')
from .base import ThemeBaseTest
class ThemePositionsTest(ThemeBaseTest):
tab = 'positions'
"""
Theme base queries plus
- 1 for positions
"""
queries = ThemeBaseTest.queries + 1
def test_queries(self):
self.do_query_test()
def test_positions(self):
self.selector_test('.position')
from .base import ThemeBaseTest
class ThemeProposalsTest(ThemeBaseTest):
tab = 'proposals'
"""
Theme base queries plus
- 1 for proposals
- 1 for related recommendations
- 1 for related dossiers
- 1 for related dossiers/documents
- 1 for related dossiers/documents/chambers
"""
queries = ThemeBaseTest.queries + 5
def test_queries(self):
self.do_query_test()
def test_proposals(self):
self.selector_test('.proposal')
......@@ -6,16 +6,28 @@ from django.views import generic
from views.dossier_ac import DossierAutocomplete, ProposalAutocomplete
from views.dossier_detail import DossierDetail
from views.dossier_list import DossierList
from views.group_ac import GroupAutocomplete
from views.group_list import GroupList
from views.representative_detail_base import RepresentativeDetailBase
from views.representative_detail_votes import RepresentativeDetailVotes
from views.representative_detail_mandates import RepresentativeDetailMandates
from views.representative_detail_positions import RepresentativeDetailPositions
from views.representative_list import RepresentativeList
from views.redirects import (RedirectGroupList, RedirectRepresentativeDetail,
RedirectGroupRepresentativeList)
from views.theme_detail import ThemeDetail
from views.redirects import (
RedirectGroupList,
RedirectRepresentativeDetail,
RedirectThemeDetail,
RedirectGroupRepresentativeList
)
from views.theme_detail_base import ThemeDetailBase
from views.theme_detail_links import ThemeDetailLinks
from views.theme_detail_dossiers import ThemeDetailDossiers
from views.theme_detail_proposals import ThemeDetailProposals
from views.theme_detail_positions import ThemeDetailPositions
from views.theme_list import ThemeList
import api
......@@ -118,13 +130,33 @@ urlpatterns = [
),
url(
r'^theme/(?P<slug>[-\w]+)/$',
ThemeDetail.as_view(),
RedirectThemeDetail.as_view(),
name='theme-detail'
),
url(
r'^votes/dossier/(?P<pk>\d+)/$',
DossierDetail.as_view(),
name='dossier-detail'
r'^theme/(?P<slug>[-\w]+)/none/$',
ThemeDetailBase.as_view(),
name='theme-none'
),
url(
r'^theme/(?P<slug>[-\w]+)/links/$',
ThemeDetailLinks.as_view(),
name='theme-links'
),
url(
r'^theme/(?P<slug>[-\w]+)/dossiers/$',
ThemeDetailDossiers.as_view(),
name='theme-dossiers'
),
url(
r'^theme/(?P<slug>[-\w]+)/proposals/$',
ThemeDetailProposals.as_view(),
name='theme-proposals'
),
url(
r'^theme/(?P<slug>[-\w]+)/positions/$',
ThemeDetailPositions.as_view(),
name='theme-positions'
),
url(r'^admin/', include(admin.site.urls)),
......
......@@ -33,3 +33,8 @@ class RedirectGroupRepresentativeList(RedirectView):
class RedirectRepresentativeDetail(RedirectView):
permanent = True
pattern_name = 'representative-votes'
class RedirectThemeDetail(RedirectView):
permanent = True
pattern_name = 'theme-links'
# coding: utf-8
from django.views import generic
from memopol_themes.models import Theme
class ThemeDetail(generic.DetailView):
queryset = Theme.objects.prefetch_related(
'links',
'dossiers__documents__chamber',
'proposals__recommendation',
'proposals__dossier__documents__chamber',
'positions__representative',
)
# coding: utf-8
from django.views import generic
from memopol_themes.models import Theme
class ThemeDetailBase(generic.DetailView):
template_name = 'memopol_themes/theme_detail.html'
queryset = Theme.objects.all()
# coding: utf-8
from .theme_detail_base import ThemeDetailBase
class ThemeDetailDossiers(ThemeDetailBase):
template_name = 'memopol_themes/theme_detail_dossiers.html'
def get_queryset(self):
qs = super(ThemeDetailDossiers, self).get_queryset()
qs = qs.prefetch_related('dossiers__documents__chamber')
return qs
def get_context_data(self, **kwargs):
c = super(ThemeDetailDossiers, self).get_context_data(**kwargs)
c['tab'] = 'dossiers'
c['dossiers'] = c['object'].dossiers.all()
return c
# coding: utf-8
from .theme_detail_base import ThemeDetailBase
class ThemeDetailLinks(ThemeDetailBase):
template_name = 'memopol_themes/theme_detail_links.html'
def get_queryset(self):
qs = super(ThemeDetailLinks, self).get_queryset()
qs = qs.prefetch_related('links')
return qs
def get_context_data(self, **kwargs):
c = super(ThemeDetailLinks, self).get_context_data(**kwargs)
c['tab'] = 'links'
c['links'] = c['object'].links.all()
return c
# coding: utf-8
from .theme_detail_base import ThemeDetailBase
class ThemeDetailPositions(ThemeDetailBase):
template_name = 'memopol_themes/theme_detail_positions.html'
def get_queryset(self):
qs = super(ThemeDetailPositions, self).get_queryset()
qs = qs.prefetch_related('positions__representative')
return qs
def get_context_data(self, **kwargs):
c = super(ThemeDetailPositions, self).get_context_data(**kwargs)
c['tab'] = 'positions'
c['positions'] = c['object'].positions.all()
return c
# coding: utf-8
from .theme_detail_base import ThemeDetailBase
class ThemeDetailProposals(ThemeDetailBase):
template_name = 'memopol_themes/theme_detail_proposals.html'
def get_queryset(self):
qs = super(ThemeDetailProposals, self).get_queryset()
qs = qs.prefetch_related(
'proposals__recommendation',
'proposals__dossier__documents__chamber',
)
return qs
def get_context_data(self, **kwargs):
c = super(ThemeDetailProposals, self).get_context_data(**kwargs)
c['tab'] = 'proposals'
c['proposals'] = c['object'].proposals.all()
return c
{% extends "base.html" %}
{% load i18n %}
{% load memopol_tags %}
{% block content %}
{% with theme=object %}
<h1>{{ theme.name }}</h1>
{% block title %}{{ theme.name }}{% endblock %}
<h2>
{% trans "Description" %}
</h2>
<p class="description">
{{ theme.description }}
</p>
{% block content %}
<div class="row" id="theme-detail">
<div class="col-sm-12">
<h1 class="text-center">{{ theme.name }}</h1>
<h2>
{% trans "Links" %}
</h2>
<table>
{% for link in theme.links.all %}
<tr>
<td>
<a class="external" href="{{ link.link }}" target="_blank">
{{ link.title }}
</a>
</td>
<td>
{{ link.datetime }}
</td>
</tr>
{% endfor %}
</table>
<h2>
{% trans "Dossiers" %}
</h2>
<div class="text-left" id="description">
{{ theme.description }}
</div>
</div>
</div>
<table>
<tr>
<th>
{% trans "Chambers" %}
</th>
<th>
{% trans "Dossier" %}
</th>
<th>
{% trans "Reference" %}
</th>
</tr>
{% for dossier in theme.dossiers.all %}
<tr>
<td>
{% for chamber in dossier.chambers %}
{{ chamber|chamber_small_icon }}
{% endfor %}
</td>
<td>
<a href="{% url 'dossier-detail' dossier.pk %}">
{{ dossier.title }}
<div class="row">
<div class="col-xs-12">
<ul class="nav nav-tabs nav-justified" role="tablist">
<li role="presentation" {% if tab == 'links' %}class="active"{% endif %}>
<a href="{% url 'theme-links' slug=theme.slug %}" role="tab">
<h3>{% trans "Links" %}</h3>
</a>
</td>
<td>
{{ dossier.reference }}
</td>
</tr>
{% endfor %}
</table>
<h2>
{% trans "Proposals" %}
</h2>
<table>
<tr>
<th>
{% trans "Chambers" %}
</th>
<th>
{% trans "Dossier" %}
</th>
<th>
{% trans "Reference" %}
<th>
{% trans "Proposal" %}
</th>
<th>
{% trans "Title" %}
</th>
<th>
{% trans "Recommendation" %}
</th>
<th>
{% trans "Status" %}
</th>
<th>{{ "for"|position_icon }}</th>
<th>{{ "against"|position_icon }}</th>
<th>{{"abstain"|position_icon }}</th>
</tr>
{% for proposal in theme.proposals.all %}
<tr>
<td>
{% for chamber in proposal.dossier.chambers %}
{{ chamber | chamber_small_icon }}
{% endfor %}
</td>
<td>
<a href="{% url 'dossier-detail' proposal.dossier.pk %}">
{{ proposal.dossier.title }}
</li>
<li role="presentation" {% if tab == 'dossiers' %}class="active"{% endif %}>
<a href="{% url 'theme-dossiers' slug=theme.slug %}" role="tab">
<h3>{% trans "Dossiers" %}</h3>
</a>
</li>
<li role="presentation" {% if tab == 'proposals' %}class="active"{% endif %}>
<a href="{% url 'theme-proposals' slug=theme.slug %}" role="tab">
<h3>{% trans "Proposals" %}</h3>
</a>
</li>
<li role="presentation" {% if tab == 'positions' %}class="active"{% endif %}>
<a href="{% url 'theme-positions' slug=theme.slug %}" role="tab">
<h3>{% trans "Public positions" %}</h3>
</a>
</li>
</ul>
<td>
{{ proposal.dossier.reference }}
</td>
<td>
{{ proposal.title }}
<br>
<small>
{{ proposal.reference }}
</small>
</td>
{% if proposal.recommendation %}
<td>{{ proposal.recommendation.title }}</td>
<td>{{ proposal.recommendation.recommendation|position_icon }}</td>
{% else %}
<td class="no-recommendation" colspan="2">No recommendation</td>
<td>{{ proposal.status }}</td>
<td>{{ proposal.total_for }}</td>
<td>{{ proposal.total_against }}</td>
<td>{{ proposal.total_abstain }}</td>
{% endif %}
</tr>
{% endfor %}
</table>
<h2>
{% trans "Positions" %}
</h2>
<div class="tab-content">
{% block theme_content %}{% endblock %}
</div>
</div>
</div>
{% endblock %}
<table>
<tr>
<th>
{% trans "Representative" %}
</th>
<th>
{% trans "Date" %}
</th>
<th>
{% trans "Position" %}
</th>
<th>
{% trans "Link" %}
</th>
</tr>
{% for position in theme.positions.all %}
<tr class="position">
<td>
{{ position.representative }}
</td>
<td>{{ position.datetime }}</td>
<td>
<a href="{{ position.get_absolute_url }}">
{{ position.text|truncatewords:8 }}