Merge branch 'elections' into 'master'

Election improvements

See merge request ae/Sith!135
This commit is contained in:
Antoine Bartuccio 2017-12-04 13:36:25 +01:00
commit bc7cfc2dba
8 changed files with 245 additions and 99 deletions

22
core/static/core/js/shorten.min.js vendored Normal file
View File

@ -0,0 +1,22 @@
// Copyright 2013 Viral Patel and other contributors
// http://viralpatel.net
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
!function(e){e.fn.shorten=function(s){"use strict";var t={showChars:100,minHideChars:10,ellipsesText:"...",moreText:"more",lessText:"less",onLess:function(){},onMore:function(){},errMsg:null,force:!1};return s&&e.extend(t,s),e(this).data("jquery.shorten")&&!t.force?!1:(e(this).data("jquery.shorten",!0),e(document).off("click",".morelink"),e(document).on({click:function(){var s=e(this);return s.hasClass("less")?(s.removeClass("less"),s.html(t.moreText),s.parent().prev().animate({height:"0%"},function(){s.parent().prev().prev().show()}).hide("fast",function(){t.onLess()})):(s.addClass("less"),s.html(t.lessText),s.parent().prev().animate({height:"100%"},function(){s.parent().prev().prev().hide()}).show("fast",function(){t.onMore()})),!1}},".morelink"),this.each(function(){var s=e(this),n=s.html(),r=s.text().length;if(r>t.showChars+t.minHideChars){var o=n.substr(0,t.showChars);if(o.indexOf("<")>=0){for(var a=!1,i="",h=0,l=[],c=null,f=0,u=0;u<=t.showChars;f++)if("<"!=n[f]||a||(a=!0,c=n.substring(f+1,n.indexOf(">",f)),"/"==c[0]?c!="/"+l[0]?t.errMsg="ERROR en HTML: the top of the stack should be the tag that closes":l.shift():"br"!=c.toLowerCase()&&l.unshift(c)),a&&">"==n[f]&&(a=!1),a)i+=n.charAt(f);else if(u++,h<=t.showChars)i+=n.charAt(f),h++;else if(l.length>0){for(j=0;j<l.length;j++)i+="</"+l[j]+">";break}o=e("<div/>").html(i+'<span class="ellip">'+t.ellipsesText+"</span>").html()}else o+=t.ellipsesText;var m='<div class="shortcontent">'+o+'</div><div class="allcontent">'+n+'</div><span><a href="javascript://nop/" class="morelink">'+t.moreText+"</a></span>";s.html(m),s.find(".allcontent").hide(),e(".shortcontent p:last",s).css("margin-bottom",0)}}))}}(jQuery);

View File

@ -0,0 +1,24 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('election', '0002_election_archived'),
]
operations = [
migrations.AlterModelOptions(
name='role',
options={'ordering': ('order',)},
),
migrations.AddField(
model_name='role',
name='order',
field=models.PositiveIntegerField(editable=False, default=0, db_index=True),
preserve_default=False,
),
]

View File

@ -1,4 +1,5 @@
from django.db import models from django.db import models
from ordered_model.models import OrderedModel
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.utils import timezone from django.utils import timezone
@ -81,10 +82,15 @@ class Election(models.Model):
results[role.title] = role.results(total_vote) results[role.title] = role.results(total_vote)
return results return results
def delete(self):
for election_list in self.election_lists.all():
election_list.delete()
super(Election, self).delete()
# Permissions # Permissions
class Role(models.Model): class Role(OrderedModel):
""" """
This class allows to create a new role avaliable for a candidature This class allows to create a new role avaliable for a candidature
""" """
@ -128,6 +134,14 @@ class ElectionList(models.Model):
title = models.CharField(_('title'), max_length=255) title = models.CharField(_('title'), max_length=255)
election = models.ForeignKey(Election, related_name='election_lists', verbose_name=_("election")) election = models.ForeignKey(Election, related_name='election_lists', verbose_name=_("election"))
def can_be_edited_by(self, user):
return user.can_edit(self.election)
def delete(self):
for candidature in self.candidatures.all():
candidature.delete()
super(ElectionList, self).delete()
def __str__(self): def __str__(self):
return self.title return self.title
@ -141,6 +155,10 @@ class Candidature(models.Model):
program = models.TextField(_('description'), null=True, blank=True) program = models.TextField(_('description'), null=True, blank=True)
election_list = models.ForeignKey(ElectionList, related_name='candidatures', verbose_name=_('election list')) election_list = models.ForeignKey(ElectionList, related_name='candidatures', verbose_name=_('election list'))
def delete(self):
for vote in self.votes.all():
vote.delete()
def can_be_edited_by(self, user): def can_be_edited_by(self, user):
return (user == self.user) or user.can_edit(self.role.election) return (user == self.user) or user.can_edit(self.role.election)

View File

@ -265,10 +265,16 @@ th {
<thead> <thead>
<th>{% trans %}Blank vote{% endtrans %}</th> <th>{% trans %}Blank vote{% endtrans %}</th>
{%- for election_list in election_lists %} {%- for election_list in election_lists %}
<th>{{ election_list.title }}</th> <th>
{{ election_list.title }}
{% if user.can_edit(election_list) and election.is_vote_editable -%}
- <a href="{{ url('election:delete_list', list_id=election_list.id) }}">{% trans %}Delete{% endtrans %}</a>
{% endif %}
</th>
{%- endfor %} {%- endfor %}
</thead> </thead>
{%- for role in election.roles.all() %} {%- set role_list = election.roles.order_by('order').all() %}
{%- for role in role_list %}
{%- set count = [0] %} {%- set count = [0] %}
{%- set role_data = election_form.data.getlist(role.title) if role.title in election_form.data else [] %} {%- set role_data = election_form.data.getlist(role.title) if role.title in election_form.data else [] %}
<tbody data-max-choice="{{role.max_choice}}" class="role{{ ' role_error' if role.title in election_form.errors else '' }}{{ ' role__multiple-choices' if role.max_choice > 1 else ''}}"> <tbody data-max-choice="{{role.max_choice}}" class="role{{ ' role_error' if role.title in election_form.errors else '' }}{{ ' role__multiple-choices' if role.max_choice > 1 else ''}}">
@ -278,9 +284,26 @@ th {
{% if user.can_edit(role) and election.is_vote_editable -%} {% if user.can_edit(role) and election.is_vote_editable -%}
<a href="{{url('election:update_role', role_id=role.id)}}">{% trans %}Edit{% endtrans %}</a> <a href="{{url('election:update_role', role_id=role.id)}}">{% trans %}Edit{% endtrans %}</a>
<a href="{{url('election:delete_role', role_id=role.id)}}">{% trans %}Delete{% endtrans %}</a> <a href="{{url('election:delete_role', role_id=role.id)}}">{% trans %}Delete{% endtrans %}</a>
<span style="float:right">
{%- if role == role_list.last() %}
<button disabled><i class="fa fa-arrow-down"></i></button>
<button disabled><i class="fa fa-caret-down"></i></button>
{%- else %}
<button type="button" onclick="window.location.replace('?role={{ role.id }}&action=bottom');"><i class="fa fa-arrow-down"></i></button>
<button type="button" onclick="window.location.replace('?role={{ role.id }}&action=down');"><i class="fa fa-caret-down"></i></button>
{%- endif %}
{% if role == role_list.first() %}
<button disabled><i class="fa fa-caret-up"></i></button>
<button disabled><i class="fa fa-arrow-up"></i></button>
{% else %}
<button type="button" onclick="window.location.replace('?role={{ role.id }}&action=up');"><i class="fa fa-caret-up"></i></button>
<button type="button" onclick="window.location.replace('?role={{ role.id }}&action=top');"><i class="fa fa-arrow-up"></i></button>
{% endif %}
</span>
{%- endif -%} {%- endif -%}
<br><span>{{ role.description }}</span> <br><span class='role__description'><p>{{ role.description }}</p></span>
{%- if role.max_choice > 1 and not election.has_voted(user) and election.can_vote(user) %} {%- if role.max_choice > 1 and not election.has_voted(user) and election.can_vote(user) %}
<br>
<strong class="role__multiple-choices-label">{% trans %}You may choose up to{% endtrans %} {{ role.max_choice }} {% trans %}people.{% endtrans %}</strong> <strong class="role__multiple-choices-label">{% trans %}You may choose up to{% endtrans %} {{ role.max_choice }} {% trans %}people.{% endtrans %}</strong>
{%- endif %} {%- endif %}
{%- if election_form.errors[role.title] is defined %} {%- if election_form.errors[role.title] is defined %}
@ -319,9 +342,6 @@ th {
</div> </div>
<figcaption class="candidate__details"> <figcaption class="candidate__details">
<cite class="candidate__full-name">{{ candidature.user.first_name }} <em class="candidate__nick-name">{{candidature.user.nick_name or ''}} </em>{{ candidature.user.last_name }}</cite> <cite class="candidate__full-name">{{ candidature.user.first_name }} <em class="candidate__nick-name">{{candidature.user.nick_name or ''}} </em>{{ candidature.user.last_name }}</cite>
{%- if not election.is_vote_finished %}
<q class="candidate__program">{{ candidature.program or '' }}</q>
{%- endif %}
{%- if user.can_edit(candidature) -%} {%- if user.can_edit(candidature) -%}
{% if election.is_vote_editable %} {% if election.is_vote_editable %}
<a href="{{url('election:update_candidate', candidature_id=candidature.id)}}">{% trans %}Edit{% endtrans %}</a> <a href="{{url('election:update_candidate', candidature_id=candidature.id)}}">{% trans %}Edit{% endtrans %}</a>
@ -330,6 +350,9 @@ th {
<a href="{{url('election:delete_candidate', candidature_id=candidature.id)}}">{% trans %}Delete{% endtrans %}</a> <a href="{{url('election:delete_candidate', candidature_id=candidature.id)}}">{% trans %}Delete{% endtrans %}</a>
{%- endif -%} {%- endif -%}
{%- endif -%} {%- endif -%}
{%- if not election.is_vote_finished %}
<q class="candidate__program">{{ candidature.program | markdown or '' }}</q>
{%- endif %}
</figcaption> </figcaption>
</figure> </figure>
{%- if election.can_vote(user) %} {%- if election.can_vote(user) %}
@ -382,6 +405,18 @@ th {
{% block script %} {% block script %}
{{ super() }} {{ super() }}
<script src="{{ static('core/js/shorten.min.js') }}"></script>
<script type="text/javascript">
$('.role__description').shorten({
moreText: "{% trans %}Show more{% endtrans %}",
lessText: "{% trans %}Show less{% endtrans %}"
});
$('.candidate__program').shorten({
moreText: "{% trans %}Show more{% endtrans %}",
lessText: "{% trans %}Show less{% endtrans %}",
showChars: 200
});
</script>
<script type="text/javascript"> <script type="text/javascript">
document.querySelectorAll('.role__multiple-choices').forEach(setupRestrictions); document.querySelectorAll('.role__multiple-choices').forEach(setupRestrictions);

View File

@ -9,6 +9,7 @@ urlpatterns = [
url(r'^(?P<election_id>[0-9]+)/edit$', ElectionUpdateView.as_view(), name='update'), url(r'^(?P<election_id>[0-9]+)/edit$', ElectionUpdateView.as_view(), name='update'),
url(r'^(?P<election_id>[0-9]+)/delete$', ElectionDeleteView.as_view(), name='delete'), url(r'^(?P<election_id>[0-9]+)/delete$', ElectionDeleteView.as_view(), name='delete'),
url(r'^(?P<election_id>[0-9]+)/list/add$', ElectionListCreateView.as_view(), name='create_list'), url(r'^(?P<election_id>[0-9]+)/list/add$', ElectionListCreateView.as_view(), name='create_list'),
url(r'^(?P<list_id>[0-9]+)/list/delete$', ElectionListDeleteView.as_view(), name='delete_list'),
url(r'^(?P<election_id>[0-9]+)/role/create$', RoleCreateView.as_view(), name='create_role'), url(r'^(?P<election_id>[0-9]+)/role/create$', RoleCreateView.as_view(), name='create_role'),
url(r'^(?P<role_id>[0-9]+)/role/edit$', RoleUpdateView.as_view(), name='update_role'), url(r'^(?P<role_id>[0-9]+)/role/edit$', RoleUpdateView.as_view(), name='update_role'),
url(r'^(?P<role_id>[0-9]+)/role/delete$', RoleDeleteView.as_view(), name='delete_role'), url(r'^(?P<role_id>[0-9]+)/role/delete$', RoleDeleteView.as_view(), name='delete_role'),

View File

@ -177,6 +177,23 @@ class ElectionDetailView(CanViewMixin, DetailView):
template_name = 'election/election_detail.jinja' template_name = 'election/election_detail.jinja'
pk_url_kwarg = "election_id" pk_url_kwarg = "election_id"
def get(self, request, *arg, **kwargs):
r = super(ElectionDetailView, self).get(request, *arg, **kwargs)
election = self.get_object()
if request.user.can_edit(election) and election.is_vote_editable:
action = request.GET.get('action', None)
role = request.GET.get('role', None)
if action and role and Role.objects.filter(id=role).exists():
if action == "up":
Role.objects.get(id=role).up()
elif action == "down":
Role.objects.get(id=role).down()
elif action == "bottom":
Role.objects.get(id=role).bottom()
elif action == "top":
Role.objects.get(id=role).top()
return r
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
""" Add additionnal data to the template """ """ Add additionnal data to the template """
kwargs = super(ElectionDetailView, self).get_context_data(**kwargs) kwargs = super(ElectionDetailView, self).get_context_data(**kwargs)
@ -538,3 +555,19 @@ class RoleDeleteView(CanEditMixin, DeleteView):
def get_success_url(self, **kwargs): def get_success_url(self, **kwargs):
return reverse_lazy('election:detail', kwargs={'election_id': self.election.id}) return reverse_lazy('election:detail', kwargs={'election_id': self.election.id})
class ElectionListDeleteView(CanEditMixin, DeleteView):
model = ElectionList
template_name = 'core/delete_confirm.jinja'
pk_url_kwarg = 'list_id'
def dispatch(self, request, *args, **kwargs):
self.object = self.get_object()
self.election = self.object.election
if not self.election.is_vote_editable:
raise PermissionDenied
return super(ElectionListDeleteView, self).dispatch(request, *args, **kwargs)
def get_success_url(self, **kwargs):
return reverse_lazy('election:detail', kwargs={'election_id': self.election.id})

View File

@ -6,7 +6,7 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-11-06 00:40+0100\n" "POT-Creation-Date: 2017-12-02 19:02+0100\n"
"PO-Revision-Date: 2016-07-18\n" "PO-Revision-Date: 2016-07-18\n"
"Last-Translator: Skia <skia@libskia.so>\n" "Last-Translator: Skia <skia@libskia.so>\n"
"Language-Team: AE info <ae.info@utbm.fr>\n" "Language-Team: AE info <ae.info@utbm.fr>\n"
@ -19,7 +19,7 @@ msgstr ""
#: accounting/models.py:61 accounting/models.py:110 accounting/models.py:138 #: accounting/models.py:61 accounting/models.py:110 accounting/models.py:138
#: accounting/models.py:197 club/models.py:47 #: accounting/models.py:197 club/models.py:47
#: core/templates/core/base.jinja:297 counter/models.py:113 #: core/templates/core/base.jinja:297 counter/models.py:113
#: counter/models.py:139 counter/models.py:183 forum/models.py:49 #: counter/models.py:140 counter/models.py:184 forum/models.py:49
#: launderette/models.py:38 launderette/models.py:84 launderette/models.py:110 #: launderette/models.py:38 launderette/models.py:84 launderette/models.py:110
#: stock/models.py:38 stock/models.py:54 stock/models.py:77 stock/models.py:97 #: stock/models.py:38 stock/models.py:54 stock/models.py:77 stock/models.py:97
msgid "name" msgid "name"
@ -66,8 +66,8 @@ msgid "account number"
msgstr "numero de compte" msgstr "numero de compte"
#: accounting/models.py:113 accounting/models.py:139 club/models.py:227 #: accounting/models.py:113 accounting/models.py:139 club/models.py:227
#: com/models.py:67 com/models.py:178 counter/models.py:148 #: com/models.py:67 com/models.py:178 counter/models.py:149
#: counter/models.py:184 trombi/models.py:149 #: counter/models.py:185 trombi/models.py:149
msgid "club" msgid "club"
msgstr "club" msgstr "club"
@ -88,13 +88,13 @@ msgstr "Compte club"
msgid "%(club_account)s on %(bank_account)s" msgid "%(club_account)s on %(bank_account)s"
msgstr "%(club_account)s sur %(bank_account)s" msgstr "%(club_account)s sur %(bank_account)s"
#: accounting/models.py:195 club/models.py:228 counter/models.py:465 #: accounting/models.py:195 club/models.py:228 counter/models.py:466
#: election/models.py:16 launderette/models.py:148 #: election/models.py:17 launderette/models.py:148
msgid "start date" msgid "start date"
msgstr "date de début" msgstr "date de début"
#: accounting/models.py:196 club/models.py:229 counter/models.py:466 #: accounting/models.py:196 club/models.py:229 counter/models.py:467
#: election/models.py:17 #: election/models.py:18
msgid "end date" msgid "end date"
msgstr "date de fin" msgstr "date de fin"
@ -107,7 +107,7 @@ msgid "club account"
msgstr "compte club" msgstr "compte club"
#: accounting/models.py:200 accounting/models.py:257 counter/models.py:53 #: accounting/models.py:200 accounting/models.py:257 counter/models.py:53
#: counter/models.py:297 #: counter/models.py:298
msgid "amount" msgid "amount"
msgstr "montant" msgstr "montant"
@ -128,18 +128,19 @@ msgid "journal"
msgstr "classeur" msgstr "classeur"
#: accounting/models.py:258 core/models.py:645 core/models.py:1046 #: accounting/models.py:258 core/models.py:645 core/models.py:1046
#: core/models.py:1090 core/models.py:1117 counter/models.py:300 #: core/models.py:1090 core/models.py:1117 counter/models.py:301
#: counter/models.py:350 counter/models.py:483 eboutic/models.py:39 #: counter/models.py:351 counter/models.py:484 eboutic/models.py:39
#: eboutic/models.py:73 forum/models.py:239 forum/models.py:314 #: eboutic/models.py:73 forum/models.py:239 forum/models.py:314
#: stock/models.py:76 #: stock/models.py:76
msgid "date" msgid "date"
msgstr "date" msgstr "date"
#: accounting/models.py:259 counter/models.py:484 stock/models.py:79 #: accounting/models.py:259 counter/models.py:115 counter/models.py:485
#: stock/models.py:79
msgid "comment" msgid "comment"
msgstr "commentaire" msgstr "commentaire"
#: accounting/models.py:260 counter/models.py:301 counter/models.py:351 #: accounting/models.py:260 counter/models.py:302 counter/models.py:352
#: subscription/models.py:55 #: subscription/models.py:55
msgid "payment method" msgid "payment method"
msgstr "méthode de paiement" msgstr "méthode de paiement"
@ -165,7 +166,7 @@ msgid "accounting type"
msgstr "type comptable" msgstr "type comptable"
#: accounting/models.py:269 accounting/models.py:371 accounting/models.py:398 #: accounting/models.py:269 accounting/models.py:371 accounting/models.py:398
#: accounting/models.py:422 core/models.py:1116 counter/models.py:342 #: accounting/models.py:422 core/models.py:1116 counter/models.py:343
msgid "label" msgid "label"
msgstr "étiquette" msgstr "étiquette"
@ -264,7 +265,7 @@ msgstr ""
"Vous devez fournir soit un type comptable simplifié ou un type comptable " "Vous devez fournir soit un type comptable simplifié ou un type comptable "
"standard" "standard"
#: accounting/models.py:366 counter/models.py:143 #: accounting/models.py:366 counter/models.py:144
msgid "code" msgid "code"
msgstr "code" msgstr "code"
@ -365,9 +366,10 @@ msgstr "Compte en banque : "
#: core/templates/core/user_edit.jinja:19 #: core/templates/core/user_edit.jinja:19
#: counter/templates/counter/last_ops.jinja:29 #: counter/templates/counter/last_ops.jinja:29
#: counter/templates/counter/last_ops.jinja:59 #: counter/templates/counter/last_ops.jinja:59
#: election/templates/election/election_detail.jinja:280 #: election/templates/election/election_detail.jinja:271
#: election/templates/election/election_detail.jinja:330 #: election/templates/election/election_detail.jinja:286
#: election/templates/election/election_detail.jinja:378 #: election/templates/election/election_detail.jinja:350
#: election/templates/election/election_detail.jinja:401
#: forum/templates/forum/macros.jinja:21 forum/templates/forum/macros.jinja:123 #: forum/templates/forum/macros.jinja:21 forum/templates/forum/macros.jinja:123
#: launderette/templates/launderette/launderette_admin.jinja:16 #: launderette/templates/launderette/launderette_admin.jinja:16
#: launderette/views.py:182 sas/templates/sas/album.jinja:26 #: launderette/views.py:182 sas/templates/sas/album.jinja:26
@ -416,9 +418,9 @@ msgstr "Nouveau compte club"
#: counter/templates/counter/counter_list.jinja:17 #: counter/templates/counter/counter_list.jinja:17
#: counter/templates/counter/counter_list.jinja:33 #: counter/templates/counter/counter_list.jinja:33
#: counter/templates/counter/counter_list.jinja:55 #: counter/templates/counter/counter_list.jinja:55
#: election/templates/election/election_detail.jinja:279 #: election/templates/election/election_detail.jinja:285
#: election/templates/election/election_detail.jinja:327 #: election/templates/election/election_detail.jinja:347
#: election/templates/election/election_detail.jinja:375 #: election/templates/election/election_detail.jinja:398
#: forum/templates/forum/macros.jinja:20 forum/templates/forum/macros.jinja:62 #: forum/templates/forum/macros.jinja:20 forum/templates/forum/macros.jinja:62
#: forum/templates/forum/macros.jinja:117 #: forum/templates/forum/macros.jinja:117
#: launderette/templates/launderette/launderette_list.jinja:16 #: launderette/templates/launderette/launderette_list.jinja:16
@ -926,21 +928,21 @@ msgstr "Vous ne pouvez pas faire de boucles dans les clubs"
msgid "A club with that unix_name already exists" msgid "A club with that unix_name already exists"
msgstr "Un club avec ce nom UNIX existe déjà." msgstr "Un club avec ce nom UNIX existe déjà."
#: club/models.py:226 counter/models.py:463 counter/models.py:481 #: club/models.py:226 counter/models.py:464 counter/models.py:482
#: eboutic/models.py:38 eboutic/models.py:72 election/models.py:140 #: eboutic/models.py:38 eboutic/models.py:72 election/models.py:154
#: launderette/models.py:114 launderette/models.py:152 sas/models.py:180 #: launderette/models.py:114 launderette/models.py:152 sas/models.py:180
#: trombi/models.py:148 #: trombi/models.py:148
msgid "user" msgid "user"
msgstr "nom d'utilisateur" msgstr "nom d'utilisateur"
#: club/models.py:230 core/models.py:180 election/models.py:139 #: club/models.py:230 core/models.py:180 election/models.py:153
#: election/models.py:155 trombi/models.py:150 #: election/models.py:173 trombi/models.py:150
msgid "role" msgid "role"
msgstr "rôle" msgstr "rôle"
#: club/models.py:232 core/models.py:66 counter/models.py:114 #: club/models.py:232 core/models.py:66 counter/models.py:114
#: counter/models.py:140 election/models.py:13 election/models.py:93 #: counter/models.py:141 election/models.py:14 election/models.py:99
#: election/models.py:141 forum/models.py:50 forum/models.py:186 #: election/models.py:155 forum/models.py:50 forum/models.py:186
msgid "description" msgid "description"
msgstr "description" msgstr "description"
@ -1312,8 +1314,8 @@ msgstr "Hebdomadaire"
msgid "Call" msgid "Call"
msgstr "Appel" msgstr "Appel"
#: com/models.py:63 com/models.py:127 com/models.py:175 election/models.py:12 #: com/models.py:63 com/models.py:127 com/models.py:175 election/models.py:13
#: election/models.py:92 election/models.py:128 forum/models.py:189 #: election/models.py:98 election/models.py:134 forum/models.py:189
#: forum/models.py:237 #: forum/models.py:237
msgid "title" msgid "title"
msgstr "titre" msgstr "titre"
@ -2001,7 +2003,7 @@ msgstr "Un utilisateur de ce nom d'utilisateur existe déjà"
#: core/templates/core/user_detail.jinja:14 #: core/templates/core/user_detail.jinja:14
#: core/templates/core/user_detail.jinja:16 #: core/templates/core/user_detail.jinja:16
#: core/templates/core/user_edit.jinja:17 #: core/templates/core/user_edit.jinja:17
#: election/templates/election/election_detail.jinja:317 #: election/templates/election/election_detail.jinja:340
#: forum/templates/forum/macros.jinja:93 forum/templates/forum/macros.jinja:95 #: forum/templates/forum/macros.jinja:93 forum/templates/forum/macros.jinja:95
#: forum/templates/forum/reply.jinja:38 forum/templates/forum/reply.jinja:40 #: forum/templates/forum/reply.jinja:38 forum/templates/forum/reply.jinja:40
#: trombi/templates/trombi/user_tools.jinja:41 #: trombi/templates/trombi/user_tools.jinja:41
@ -3273,67 +3275,67 @@ msgstr "clients"
msgid "Not enough money" msgid "Not enough money"
msgstr "Solde insuffisant" msgstr "Solde insuffisant"
#: counter/models.py:118 counter/models.py:141 #: counter/models.py:119 counter/models.py:142
msgid "product type" msgid "product type"
msgstr "type du produit" msgstr "type du produit"
#: counter/models.py:144 #: counter/models.py:145
msgid "purchase price" msgid "purchase price"
msgstr "prix d'achat" msgstr "prix d'achat"
#: counter/models.py:145 #: counter/models.py:146
msgid "selling price" msgid "selling price"
msgstr "prix de vente" msgstr "prix de vente"
#: counter/models.py:146 #: counter/models.py:147
msgid "special selling price" msgid "special selling price"
msgstr "prix de vente spécial" msgstr "prix de vente spécial"
#: counter/models.py:147 #: counter/models.py:148
msgid "icon" msgid "icon"
msgstr "icône" msgstr "icône"
#: counter/models.py:149 #: counter/models.py:150
msgid "limit age" msgid "limit age"
msgstr "âge limite" msgstr "âge limite"
#: counter/models.py:150 #: counter/models.py:151
msgid "tray price" msgid "tray price"
msgstr "prix plateau" msgstr "prix plateau"
#: counter/models.py:151 #: counter/models.py:152
msgid "parent product" msgid "parent product"
msgstr "produit parent" msgstr "produit parent"
#: counter/models.py:153 #: counter/models.py:154
msgid "buying groups" msgid "buying groups"
msgstr "groupe d'achat" msgstr "groupe d'achat"
#: counter/models.py:154 election/models.py:36 #: counter/models.py:155 election/models.py:37
msgid "archived" msgid "archived"
msgstr "archivé" msgstr "archivé"
#: counter/models.py:157 counter/models.py:566 #: counter/models.py:158 counter/models.py:567
msgid "product" msgid "product"
msgstr "produit" msgstr "produit"
#: counter/models.py:185 #: counter/models.py:186
msgid "products" msgid "products"
msgstr "produits" msgstr "produits"
#: counter/models.py:186 #: counter/models.py:187
msgid "counter type" msgid "counter type"
msgstr "type de comptoir" msgstr "type de comptoir"
#: counter/models.py:188 #: counter/models.py:189
msgid "Bar" msgid "Bar"
msgstr "Bar" msgstr "Bar"
#: counter/models.py:188 #: counter/models.py:189
msgid "Office" msgid "Office"
msgstr "Bureau" msgstr "Bureau"
#: counter/models.py:188 counter/templates/counter/counter_list.jinja:11 #: counter/models.py:189 counter/templates/counter/counter_list.jinja:11
#: eboutic/templates/eboutic/eboutic_main.jinja:4 #: eboutic/templates/eboutic/eboutic_main.jinja:4
#: eboutic/templates/eboutic/eboutic_main.jinja:24 #: eboutic/templates/eboutic/eboutic_main.jinja:24
#: eboutic/templates/eboutic/eboutic_makecommand.jinja:8 #: eboutic/templates/eboutic/eboutic_makecommand.jinja:8
@ -3342,62 +3344,62 @@ msgstr "Bureau"
msgid "Eboutic" msgid "Eboutic"
msgstr "Eboutic" msgstr "Eboutic"
#: counter/models.py:189 #: counter/models.py:190
msgid "sellers" msgid "sellers"
msgstr "vendeurs" msgstr "vendeurs"
#: counter/models.py:192 launderette/models.py:151 #: counter/models.py:193 launderette/models.py:151
msgid "token" msgid "token"
msgstr "jeton" msgstr "jeton"
#: counter/models.py:195 counter/models.py:464 counter/models.py:482 #: counter/models.py:196 counter/models.py:465 counter/models.py:483
#: launderette/models.py:39 stock/models.py:39 #: launderette/models.py:39 stock/models.py:39
msgid "counter" msgid "counter"
msgstr "comptoir" msgstr "comptoir"
#: counter/models.py:303 #: counter/models.py:304
msgid "bank" msgid "bank"
msgstr "banque" msgstr "banque"
#: counter/models.py:305 counter/models.py:353 #: counter/models.py:306 counter/models.py:354
msgid "is validated" msgid "is validated"
msgstr "est validé" msgstr "est validé"
#: counter/models.py:308 #: counter/models.py:309
msgid "refilling" msgid "refilling"
msgstr "rechargement" msgstr "rechargement"
#: counter/models.py:346 eboutic/models.py:129 #: counter/models.py:347 eboutic/models.py:129
msgid "unit price" msgid "unit price"
msgstr "prix unitaire" msgstr "prix unitaire"
#: counter/models.py:347 counter/models.py:555 eboutic/models.py:130 #: counter/models.py:348 counter/models.py:556 eboutic/models.py:130
msgid "quantity" msgid "quantity"
msgstr "quantité" msgstr "quantité"
#: counter/models.py:352 #: counter/models.py:353
msgid "Sith account" msgid "Sith account"
msgstr "Compte utilisateur" msgstr "Compte utilisateur"
#: counter/models.py:352 sith/settings.py:368 sith/settings.py:373 #: counter/models.py:353 sith/settings.py:368 sith/settings.py:373
#: sith/settings.py:395 #: sith/settings.py:395
msgid "Credit card" msgid "Credit card"
msgstr "Carte bancaire" msgstr "Carte bancaire"
#: counter/models.py:356 #: counter/models.py:357
msgid "selling" msgid "selling"
msgstr "vente" msgstr "vente"
#: counter/models.py:375 #: counter/models.py:376
msgid "Unknown event" msgid "Unknown event"
msgstr "Événement inconnu" msgstr "Événement inconnu"
#: counter/models.py:376 #: counter/models.py:377
#, python-format #, python-format
msgid "Eticket bought for the event %(event)s" msgid "Eticket bought for the event %(event)s"
msgstr "Eticket acheté pour l'événement %(event)s" msgstr "Eticket acheté pour l'événement %(event)s"
#: counter/models.py:378 counter/models.py:390 #: counter/models.py:379 counter/models.py:391
#, python-format #, python-format
msgid "" msgid ""
"You bought an eticket for the event %(event)s.\n" "You bought an eticket for the event %(event)s.\n"
@ -3406,51 +3408,51 @@ msgstr ""
"Vous avez acheté un Eticket pour l'événement %(event)s.\n" "Vous avez acheté un Eticket pour l'événement %(event)s.\n"
"Vous pouvez le télécharger sur cette page: %(url)s" "Vous pouvez le télécharger sur cette page: %(url)s"
#: counter/models.py:467 #: counter/models.py:468
msgid "last activity date" msgid "last activity date"
msgstr "dernière activité" msgstr "dernière activité"
#: counter/models.py:470 #: counter/models.py:471
msgid "permanency" msgid "permanency"
msgstr "permanence" msgstr "permanence"
#: counter/models.py:485 #: counter/models.py:486
msgid "emptied" msgid "emptied"
msgstr "coffre vidée" msgstr "coffre vidée"
#: counter/models.py:488 #: counter/models.py:489
msgid "cash register summary" msgid "cash register summary"
msgstr "relevé de caisse" msgstr "relevé de caisse"
#: counter/models.py:553 #: counter/models.py:554
msgid "cash summary" msgid "cash summary"
msgstr "relevé" msgstr "relevé"
#: counter/models.py:554 #: counter/models.py:555
msgid "value" msgid "value"
msgstr "valeur" msgstr "valeur"
#: counter/models.py:556 #: counter/models.py:557
msgid "check" msgid "check"
msgstr "chèque" msgstr "chèque"
#: counter/models.py:559 #: counter/models.py:560
msgid "cash register summary item" msgid "cash register summary item"
msgstr "élément de relevé de caisse" msgstr "élément de relevé de caisse"
#: counter/models.py:567 #: counter/models.py:568
msgid "banner" msgid "banner"
msgstr "bannière" msgstr "bannière"
#: counter/models.py:568 #: counter/models.py:569
msgid "event date" msgid "event date"
msgstr "date de l'événement" msgstr "date de l'événement"
#: counter/models.py:569 #: counter/models.py:570
msgid "event title" msgid "event title"
msgstr "titre de l'événement" msgstr "titre de l'événement"
#: counter/models.py:570 #: counter/models.py:571
msgid "secret" msgid "secret"
msgstr "secret" msgstr "secret"
@ -3906,49 +3908,49 @@ msgstr "Retourner à l'eboutic"
msgid "You do not have enough money to buy the basket" msgid "You do not have enough money to buy the basket"
msgstr "Vous n'avez pas assez d'argent pour acheter le panier" msgstr "Vous n'avez pas assez d'argent pour acheter le panier"
#: election/models.py:14 #: election/models.py:15
msgid "start candidature" msgid "start candidature"
msgstr "début des candidatures" msgstr "début des candidatures"
#: election/models.py:15 #: election/models.py:16
msgid "end candidature" msgid "end candidature"
msgstr "fin des candidatures" msgstr "fin des candidatures"
#: election/models.py:21 #: election/models.py:22
msgid "edit groups" msgid "edit groups"
msgstr "groupe d'édition" msgstr "groupe d'édition"
#: election/models.py:25 #: election/models.py:26
msgid "view groups" msgid "view groups"
msgstr "groupe de vue" msgstr "groupe de vue"
#: election/models.py:29 #: election/models.py:30
msgid "vote groups" msgid "vote groups"
msgstr "groupe de vote" msgstr "groupe de vote"
#: election/models.py:33 #: election/models.py:34
msgid "candidature groups" msgid "candidature groups"
msgstr "groupe de candidature" msgstr "groupe de candidature"
#: election/models.py:91 election/models.py:129 #: election/models.py:97 election/models.py:135
msgid "election" msgid "election"
msgstr "élection" msgstr "élection"
#: election/models.py:94 #: election/models.py:100
msgid "max choice" msgid "max choice"
msgstr "nombre de choix maxi" msgstr "nombre de choix maxi"
#: election/models.py:142 #: election/models.py:156
msgid "election list" msgid "election list"
msgstr "liste électorale" msgstr "liste électorale"
#: election/models.py:156 #: election/models.py:174
msgid "candidature" msgid "candidature"
msgstr "candidature" msgstr "candidature"
#: election/templates/election/candidate_form.jinja:4 #: election/templates/election/candidate_form.jinja:4
#: election/templates/election/candidate_form.jinja:13 #: election/templates/election/candidate_form.jinja:13
#: election/templates/election/election_detail.jinja:366 #: election/templates/election/election_detail.jinja:389
msgid "Candidate" msgid "Candidate"
msgstr "Candidater" msgstr "Candidater"
@ -3994,40 +3996,50 @@ msgstr "Vous avez déjà voté pour cette élection."
msgid "Blank vote" msgid "Blank vote"
msgstr "Vote blanc" msgstr "Vote blanc"
#: election/templates/election/election_detail.jinja:284 #: election/templates/election/election_detail.jinja:307
msgid "You may choose up to" msgid "You may choose up to"
msgstr "Vous pouvez choisir jusqu'à" msgstr "Vous pouvez choisir jusqu'à"
#: election/templates/election/election_detail.jinja:284 #: election/templates/election/election_detail.jinja:307
msgid "people." msgid "people."
msgstr "personne(s)" msgstr "personne(s)"
#: election/templates/election/election_detail.jinja:298 #: election/templates/election/election_detail.jinja:321
msgid "Choose blank vote" msgid "Choose blank vote"
msgstr "Choisir de voter blanc" msgstr "Choisir de voter blanc"
#: election/templates/election/election_detail.jinja:305 #: election/templates/election/election_detail.jinja:328
#: election/templates/election/election_detail.jinja:345 #: election/templates/election/election_detail.jinja:368
msgid "votes" msgid "votes"
msgstr "votes" msgstr "votes"
#: election/templates/election/election_detail.jinja:338 #: election/templates/election/election_detail.jinja:361
#: launderette/templates/launderette/launderette_book.jinja:12 #: launderette/templates/launderette/launderette_book.jinja:12
msgid "Choose" msgid "Choose"
msgstr "Choisir" msgstr "Choisir"
#: election/templates/election/election_detail.jinja:361 #: election/templates/election/election_detail.jinja:384
msgid "Submit the vote !" msgid "Submit the vote !"
msgstr "Envoyer le vote !" msgstr "Envoyer le vote !"
#: election/templates/election/election_detail.jinja:369 #: election/templates/election/election_detail.jinja:392
msgid "Add a new list" msgid "Add a new list"
msgstr "Ajouter une nouvelle liste" msgstr "Ajouter une nouvelle liste"
#: election/templates/election/election_detail.jinja:373 #: election/templates/election/election_detail.jinja:396
msgid "Add a new role" msgid "Add a new role"
msgstr "Ajouter un nouveau rôle" msgstr "Ajouter un nouveau rôle"
#: election/templates/election/election_detail.jinja:411
#: election/templates/election/election_detail.jinja:415
msgid "Show more"
msgstr "Montrer plus"
#: election/templates/election/election_detail.jinja:412
#: election/templates/election/election_detail.jinja:416
msgid "Show less"
msgstr "Montrer moins"
#: election/templates/election/election_list.jinja:5 #: election/templates/election/election_list.jinja:5
msgid "Election list" msgid "Election list"
msgstr "Liste des élections" msgstr "Liste des élections"

View File

@ -13,5 +13,6 @@ django-haystack
whoosh whoosh
django-debug-toolbar django-debug-toolbar
libsass libsass
django-ordered-model
pygraphviz pygraphviz
# mysqlclient # mysqlclient