diff --git a/accounting/templates/accounting/journal_details.jinja b/accounting/templates/accounting/journal_details.jinja index aa203eaa..aa3d1f19 100644 --- a/accounting/templates/accounting/journal_details.jinja +++ b/accounting/templates/accounting/journal_details.jinja @@ -53,7 +53,7 @@ {% endif %} {{ o.remark }} {% if o.invoice %} - {{ o.invoice.name }} + {{ o.invoice.name }} {% else %} - {% endif %} diff --git a/accounting/views.py b/accounting/views.py index 149bd861..8a80992e 100644 --- a/accounting/views.py +++ b/accounting/views.py @@ -4,10 +4,9 @@ from django.shortcuts import render from django.core.urlresolvers import reverse_lazy from django.forms.models import modelform_factory from django.forms import HiddenInput -from django.forms.extras.widgets import SelectDateWidget from core.views import CanViewMixin, CanEditMixin, CanEditPropMixin, CanCreateMixin -from core.views.forms import SelectFile +from core.views.forms import SelectFile, SelectDate from accounting.models import BankAccount, ClubAccount, GeneralJournal, Operation, AccountingType, Company # Accounting types @@ -168,7 +167,7 @@ class OperationCreateView(CanCreateMixin, CreateView): form_class = modelform_factory(Operation, fields=['amount', 'label', 'remark', 'journal', 'target_type', 'target_id', 'target_label', 'date', 'mode', 'cheque_number', 'invoice', 'accounting_type', 'done'], - widgets={'journal': HiddenInput, 'date': SelectDateWidget}) + widgets={'journal': HiddenInput, 'date': SelectDate}) template_name = 'core/create.jinja' def get_initial(self): @@ -188,7 +187,7 @@ class OperationEditView(CanEditMixin, UpdateView): form_class = modelform_factory(Operation, fields = ['amount', 'label', 'remark', 'target_type', 'target_id', 'target_label', 'date', 'mode', 'cheque_number', 'invoice', 'accounting_type', 'done'], - widgets={'date': SelectDateWidget, 'invoice': SelectFile}) + widgets={'date': SelectDate, 'invoice': SelectFile}) template_name = 'core/edit.jinja' # Company views diff --git a/core/management/commands/populate.py b/core/management/commands/populate.py index bccdc451..e82f56b2 100644 --- a/core/management/commands/populate.py +++ b/core/management/commands/populate.py @@ -38,6 +38,7 @@ class Command(BaseCommand): is_superuser=True, is_staff=True) root.set_password("plop") root.save() + SithFile(parent=None, name="profiles", is_folder=True, owner=root).save() home_root = SithFile(parent=None, name="users", is_folder=True, owner=root) home_root.save() club_root = SithFile(parent=None, name="clubs", is_folder=True, owner=root) diff --git a/core/migrations/0003_auto_20160810_1949.py b/core/migrations/0003_auto_20160810_1949.py new file mode 100644 index 00000000..10c42712 --- /dev/null +++ b/core/migrations/0003_auto_20160810_1949.py @@ -0,0 +1,29 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0002_user_home'), + ] + + operations = [ + migrations.AddField( + model_name='user', + name='avatar_pict', + field=models.OneToOneField(related_name='avatar_of', verbose_name='avatar', to='core.SithFile', null=True, blank=True), + ), + migrations.AddField( + model_name='user', + name='profile_pict', + field=models.OneToOneField(related_name='profile_of', verbose_name='profile', to='core.SithFile', null=True, blank=True), + ), + migrations.AddField( + model_name='user', + name='scrub_pict', + field=models.OneToOneField(related_name='scrub_of', verbose_name='scrub', to='core.SithFile', null=True, blank=True), + ), + ] diff --git a/core/migrations/0004_auto_20160811_0206.py b/core/migrations/0004_auto_20160811_0206.py new file mode 100644 index 00000000..a0646a2f --- /dev/null +++ b/core/migrations/0004_auto_20160811_0206.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0003_auto_20160810_1949'), + ] + + operations = [ + migrations.AlterField( + model_name='user', + name='nick_name', + field=models.CharField(verbose_name='nick name', max_length=30, blank=True), + ), + ] diff --git a/core/migrations/0005_auto_20160811_0319.py b/core/migrations/0005_auto_20160811_0319.py new file mode 100644 index 00000000..13c5bab3 --- /dev/null +++ b/core/migrations/0005_auto_20160811_0319.py @@ -0,0 +1,65 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models +import core.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0004_auto_20160811_0206'), + ] + + operations = [ + migrations.AddField( + model_name='user', + name='department', + field=models.CharField(max_length=15, choices=[('TC', 'TC'), ('IMSI', 'IMSI'), ('IMAP', 'IMAP'), ('INFO', 'INFO'), ('GI', 'GI'), ('E', 'E'), ('EE', 'EE'), ('GESC', 'GESC'), ('GMC', 'GMC'), ('MC', 'MC'), ('EDIM', 'EDIM'), ('HUMAN', 'Humanities'), ('NA', 'N/A')], default='NA', verbose_name='department'), + ), + migrations.AddField( + model_name='user', + name='dpt_option', + field=models.CharField(max_length=32, default='', verbose_name='dpt option'), + ), + migrations.AddField( + model_name='user', + name='forum_signature', + field=models.TextField(max_length=256, default='', verbose_name='forum signature'), + ), + migrations.AddField( + model_name='user', + name='promo', + field=models.IntegerField(blank=True, null=True, validators=[core.models.validate_promo], verbose_name='promo'), + ), + migrations.AddField( + model_name='user', + name='quote', + field=models.CharField(max_length=64, default='', verbose_name='quote'), + ), + migrations.AddField( + model_name='user', + name='role', + field=models.CharField(max_length=15, choices=[('STUDENT', 'Student'), ('ADMINISTRATIVE', 'Administrative agent'), ('TEACHER', 'Teacher'), ('AGENT', 'Agent'), ('DOCTOR', 'Doctor'), ('FORMER STUDENT', 'Former student'), ('SERVICE', 'Service')], default='STUDENT', verbose_name='role'), + ), + migrations.AddField( + model_name='user', + name='school', + field=models.CharField(max_length=32, default='', verbose_name='school'), + ), + migrations.AddField( + model_name='user', + name='semester', + field=models.CharField(max_length=5, default='', verbose_name='semester'), + ), + migrations.AddField( + model_name='user', + name='sex', + field=models.CharField(max_length=10, choices=[('MAN', 'Man'), ('WOMAN', 'Woman')], default='MAN', verbose_name='sex'), + ), + migrations.AddField( + model_name='user', + name='tshirt_size', + field=models.CharField(max_length=5, choices=[('-', '-'), ('XS', 'XS'), ('S', 'S'), ('M', 'M'), ('L', 'L'), ('XL', 'XL'), ('XXL', 'XXL'), ('XXXL', 'XXXL')], default='M', verbose_name='tshirt size'), + ), + ] diff --git a/core/models.py b/core/models.py index ad414f78..554ba3fd 100644 --- a/core/models.py +++ b/core/models.py @@ -7,7 +7,7 @@ from django.core.exceptions import ValidationError from django.core.urlresolvers import reverse from django.conf import settings from django.db import transaction -from datetime import datetime, timedelta +from datetime import datetime, timedelta, date import unicodedata @@ -46,6 +46,15 @@ class RealGroup(Group): class Meta: proxy = True +def validate_promo(value): + start_year = settings.SITH_SCHOOL_START_YEAR + delta = (date.today()+timedelta(days=180)).year - start_year + if value < 0 or delta < value: + raise ValidationError( + _('%(value)s is not a valid promo (between 0 and %(end)s)'), + params={'value': value, 'end': delta}, + ) + class User(AbstractBaseUser): """ Defines the base user class, useable in every app @@ -77,7 +86,7 @@ class User(AbstractBaseUser): last_name = models.CharField(_('last name'), max_length=30) email = models.EmailField(_('email address'), unique=True) date_of_birth = models.DateField(_('date of birth'), blank=True, null=True) - nick_name = models.CharField(max_length=30, blank=True) + nick_name = models.CharField(_('nick name'), max_length=30, blank=True) is_staff = models.BooleanField( _('staff status'), default=False, @@ -101,6 +110,51 @@ class User(AbstractBaseUser): ) groups = models.ManyToManyField(RealGroup, related_name='users', blank=True) home = models.OneToOneField('SithFile', related_name='home_of', verbose_name=_("home"), null=True, blank=True) + profile_pict = models.OneToOneField('SithFile', related_name='profile_of', verbose_name=_("profile"), null=True, blank=True) + avatar_pict = models.OneToOneField('SithFile', related_name='avatar_of', verbose_name=_("avatar"), null=True, blank=True) + scrub_pict = models.OneToOneField('SithFile', related_name='scrub_of', verbose_name=_("scrub"), null=True, blank=True) + sex = models.CharField(_("sex"), max_length=10, choices=[("MAN", _("Man")), ("WOMAN", _("Woman"))], default="MAN") + tshirt_size = models.CharField(_("tshirt size"), max_length=5, choices=[ + ("-", _("-")), + ("XS", _("XS")), + ("S", _("S")), + ("M", _("M")), + ("L", _("L")), + ("XL", _("XL")), + ("XXL", _("XXL")), + ("XXXL", _("XXXL")), + ], default="M") + role = models.CharField(_("role"), max_length=15, choices=[ + ("STUDENT", _("Student")), + ("ADMINISTRATIVE", _("Administrative agent")), + ("TEACHER", _("Teacher")), + ("AGENT", _("Agent")), + ("DOCTOR", _("Doctor")), + ("FORMER STUDENT", _("Former student")), + ("SERVICE", _("Service")), + ], default="STUDENT") + department = models.CharField(_("department"), max_length=15, choices=[ + ("TC", _("TC")), + ("IMSI", _("IMSI")), + ("IMAP", _("IMAP")), + ("INFO", _("INFO")), + ("GI", _("GI")), + ("E", _("E")), + ("EE", _("EE")), + ("GESC", _("GESC")), + ("GMC", _("GMC")), + ("MC", _("MC")), + ("EDIM", _("EDIM")), + ("HUMAN", _("Humanities")), + ("NA", _("N/A")), + ], default="NA") + dpt_option = models.CharField(_("dpt option"), max_length=32, default="") + semester = models.CharField(_("semester"), max_length=5, default="") + quote = models.CharField(_("quote"), max_length=64, default="") + school = models.CharField(_("school"), max_length=32, default="") + promo = models.IntegerField(_("promo"), validators=[validate_promo], null=True, blank=True) + forum_signature = models.TextField(_("forum signature"), max_length=256, default="") + # TODO: add phone numbers with https://github.com/stefanfoulis/django-phonenumber-field objects = UserManager() @@ -341,6 +395,15 @@ class SithFile(models.Model): def is_owned_by(self, user): return user.id == self.owner.id + def can_be_viewed_by(self, user): + if hasattr(self, 'profile_of'): + return user.can_view(self.profile_of) + if hasattr(self, 'avatar_of'): + return user.can_view(self.avatar_of) + if hasattr(self, 'scrub_of'): + return user.can_view(self.scrub_of) + return False + def delete(self): for c in self.children.all(): c.delete() @@ -422,6 +485,9 @@ class SithFile(models.Model): def get_display_name(self): return self.name + def get_download_url(self): + return reverse('core:download', kwargs={'file_id': self.id}) + class LockError(Exception): """There was a lock error on the object""" pass diff --git a/core/static/core/form.css b/core/static/core/form.css index 9dbe2777..ff65340e 100644 --- a/core/static/core/form.css +++ b/core/static/core/form.css @@ -2,6 +2,11 @@ Super Form Reset ----------------------------------------------------------------------------------------------------*/ +form { + margin: 0px auto; + width: 60%; +} + input, label, select, @@ -22,6 +27,10 @@ textarea font-family: Arial; } +label { + min-width: 50%; +} + /* Remove the stupid outer glow in Webkit */ input:focus { @@ -70,7 +79,8 @@ input[type=tel], input[type=text], input[type=time], input[type=url], -input[type=week] +input[type=week], +textarea { background-color: white; border: 1px solid black; diff --git a/core/static/core/img/promo_01.png b/core/static/core/img/promo_01.png new file mode 100644 index 00000000..ba1e5a96 Binary files /dev/null and b/core/static/core/img/promo_01.png differ diff --git a/core/static/core/img/promo_02.png b/core/static/core/img/promo_02.png new file mode 100644 index 00000000..29593a17 Binary files /dev/null and b/core/static/core/img/promo_02.png differ diff --git a/core/static/core/img/promo_03.png b/core/static/core/img/promo_03.png new file mode 100644 index 00000000..2d1ce707 Binary files /dev/null and b/core/static/core/img/promo_03.png differ diff --git a/core/static/core/img/promo_04.png b/core/static/core/img/promo_04.png new file mode 100644 index 00000000..1011a729 Binary files /dev/null and b/core/static/core/img/promo_04.png differ diff --git a/core/static/core/img/promo_05.png b/core/static/core/img/promo_05.png new file mode 100644 index 00000000..394ba362 Binary files /dev/null and b/core/static/core/img/promo_05.png differ diff --git a/core/static/core/img/promo_06.png b/core/static/core/img/promo_06.png new file mode 100644 index 00000000..c837dadf Binary files /dev/null and b/core/static/core/img/promo_06.png differ diff --git a/core/static/core/img/promo_07.png b/core/static/core/img/promo_07.png new file mode 100644 index 00000000..ae3bafb0 Binary files /dev/null and b/core/static/core/img/promo_07.png differ diff --git a/core/static/core/img/promo_08.png b/core/static/core/img/promo_08.png new file mode 100644 index 00000000..6897270c Binary files /dev/null and b/core/static/core/img/promo_08.png differ diff --git a/core/static/core/img/promo_09.png b/core/static/core/img/promo_09.png new file mode 100644 index 00000000..fea3671d Binary files /dev/null and b/core/static/core/img/promo_09.png differ diff --git a/core/static/core/img/promo_10.png b/core/static/core/img/promo_10.png new file mode 100644 index 00000000..7d553e20 Binary files /dev/null and b/core/static/core/img/promo_10.png differ diff --git a/core/static/core/img/promo_11.png b/core/static/core/img/promo_11.png new file mode 100644 index 00000000..ca8487fb Binary files /dev/null and b/core/static/core/img/promo_11.png differ diff --git a/core/static/core/img/promo_12.png b/core/static/core/img/promo_12.png new file mode 100644 index 00000000..8afefc16 Binary files /dev/null and b/core/static/core/img/promo_12.png differ diff --git a/core/static/core/img/promo_13.png b/core/static/core/img/promo_13.png new file mode 100644 index 00000000..8affbc10 Binary files /dev/null and b/core/static/core/img/promo_13.png differ diff --git a/core/static/core/img/promo_14.png b/core/static/core/img/promo_14.png new file mode 100644 index 00000000..7085991c Binary files /dev/null and b/core/static/core/img/promo_14.png differ diff --git a/core/static/core/img/promo_15.png b/core/static/core/img/promo_15.png new file mode 100644 index 00000000..dcfa5e8f Binary files /dev/null and b/core/static/core/img/promo_15.png differ diff --git a/core/static/core/img/promo_16.png b/core/static/core/img/promo_16.png new file mode 100644 index 00000000..be96e7ba Binary files /dev/null and b/core/static/core/img/promo_16.png differ diff --git a/core/static/core/js/script.js b/core/static/core/js/script.js index d889750f..9cf2944e 100644 --- a/core/static/core/js/script.js +++ b/core/static/core/js/script.js @@ -1,11 +1,29 @@ console.log('Guy'); $( function() { - dialog = $( ".choose_file_widget" ).dialog({ + buttons = $(".choose_file_button"); + popups = $(".choose_file_widget"); + popups.dialog({ autoOpen: false, modal: true, + width: "80%", + minHeight: "300", + buttons: { + "Choose": function() { + console.log($("#file_id")); + $("input[name="+$(this).attr('name')+"]").attr('value', $("#file_id").attr('value')); + $( this ).dialog( "close" ); + } + } + }); + $('.select_date').datepicker({ + changeMonth: true, + changeYear: true }); $( ".choose_file_button" ).button().on( "click", function() { - dialog.dialog( "open" ); + popup = popups.filter("[name="+$(this).attr('name')+"]"); + console.log(popup); + popup.html(''); + popup.dialog({title: $(this).attr('name')}).dialog( "open" ); }); } ); diff --git a/core/static/core/style.css b/core/static/core/style.css index fe517c12..1f9244cd 100644 --- a/core/static/core/style.css +++ b/core/static/core/style.css @@ -118,12 +118,16 @@ ul, ol { } table { width: 100%; + font-size: 0.90em; } td { padding: 4px; border: solid 1px black; border-collapse: collapse; vertical-align: top; + overflow: hidden; + text-overflow: ellipsis; + max-width: 0; } td>ul { margin-top: 0px; @@ -152,7 +156,27 @@ tbody>tr:hover { } /*-----------------------------USER PROFILE----------------------------*/ -.user_profile { +#user_profile { + width: 80%; + margin: 0px auto; + padding: 10px; + overflow: auto; +} +#user_profile h4 { border-bottom: 1px solid grey; max-width: 60%; } +#user_profile #pictures { + width: 30%; + float: right; + font-style: italic; +} +#user_profile #nickname { + font-style: italic; +} +#user_profile #pictures img { + max-width: 96%; + max-height: 96%; +} +#user_profile .promo_pict { + height: 45px; } /*---------------------------------PAGE--------------------------------*/ .page_content { diff --git a/core/templates/core/base.jinja b/core/templates/core/base.jinja index eaf51cf4..815e60a0 100644 --- a/core/templates/core/base.jinja +++ b/core/templates/core/base.jinja @@ -60,23 +60,25 @@ {{ tests }} {% endblock %} --> + {% block script %} + {% endblock %} diff --git a/core/templates/core/edit.jinja b/core/templates/core/edit.jinja index 2c9c06c0..c27a3cd3 100644 --- a/core/templates/core/edit.jinja +++ b/core/templates/core/edit.jinja @@ -1,5 +1,9 @@ {% extends "core/base.jinja" %} +{% block title %} +{% trans obj=object %}Edit {{ obj }}{% endtrans %} +{% endblock %} + {% block content %}

{% trans obj=object %}Edit {{ obj }}{% endtrans %}

diff --git a/core/templates/core/file_detail.jinja b/core/templates/core/file_detail.jinja index 80609977..1585ca9a 100644 --- a/core/templates/core/file_detail.jinja +++ b/core/templates/core/file_detail.jinja @@ -42,8 +42,18 @@ {% if not file.home_of and not file.home_of_club and file.parent %}

{% trans %}Delete{% endtrans %}

{% endif %} +{% if popup %} +{% endif %} +{% endblock %} + +{% block script %} +{{ super() }} +{% if popup and file.is_file %} + +{% endif %} {% endblock %} - diff --git a/core/templates/core/login.jinja b/core/templates/core/login.jinja index 9e7fadd7..35efa68c 100644 --- a/core/templates/core/login.jinja +++ b/core/templates/core/login.jinja @@ -21,7 +21,9 @@ {% csrf_token %} -{{ form.as_p() }} +

{{ form.username.errors }}

+

{{ form.password.errors }}{{ form.password }}

diff --git a/core/templates/core/user_detail.jinja b/core/templates/core/user_detail.jinja index dce8fea4..0e40bafc 100644 --- a/core/templates/core/user_detail.jinja +++ b/core/templates/core/user_detail.jinja @@ -5,12 +5,26 @@ {% endblock %} {% block infos %} -

{% trans %}User Profile{% endtrans %}

-
+
+
+ {% if profile.profile_pict %} + {% trans %}Profile{% endtrans %} + {% endif %} +

{{ profile.quote }}

+

{{ profile.get_full_name() }}

-

{{ profile.nick_name }}

+

« {{ profile.nick_name }} »

{% trans %}Born: {% endtrans %}{{ profile.date_of_birth|date("d/m/Y") }}

+

{{ profile.department }}{{ profile.semester }} + {% if profile.dpt_option %} +
{% trans %}Option: {% endtrans %}{{ profile.dpt_option }} + {% endif %} +

+ {% if profile.promo %} +

Promo {{ profile.promo }} + {% trans %}Promo: {% endtrans %}{{ profile.promo }}

+ {% endif %}
{% if user.membership.filter(end_date=None).exists() or user.is_in_group(settings.SITH_MAIN_BOARD_GROUP) %} diff --git a/core/templates/core/user_edit.jinja b/core/templates/core/user_edit.jinja index c21e39eb..d862c150 100644 --- a/core/templates/core/user_edit.jinja +++ b/core/templates/core/user_edit.jinja @@ -1,15 +1,31 @@ -{% extends "core/base.jinja" %} +{% extends "core/user_base.jinja" %} -{% block content %} +{% block infos %}

{% trans %}Edit user profile{% endtrans %}

-
+ {% csrf_token %} - {{ form.as_p() }} + {% for field in form %} +

{{ field.errors }} {{ field }}

+ {% endfor %}

+

{% trans %}Username: {% endtrans %}{{ form.instance.username }}

+ {% if form.instance.customer %} +

{% trans %}Account number: {% endtrans %}{{ form.instance.customer.account_id }}

+ {% endif %} + {% if form.instance == user %} +

{% trans %}Change my password{% endtrans %}

+ {% endif %}
-{% if form.instance == user %} -

{% trans %}Change my password{% endtrans %}

-{% endif %} {% endblock %} diff --git a/core/templates/core/user_group.jinja b/core/templates/core/user_group.jinja index b062cafb..f4471ea3 100644 --- a/core/templates/core/user_group.jinja +++ b/core/templates/core/user_group.jinja @@ -1,6 +1,6 @@ -{% extends "core/base.jinja" %} +{% extends "core/user_base.jinja" %} -{% block content %} +{% block infos %}

{% trans user_name=profile.get_full_name() %}Edit user groups for {{ user_name }}{% endtrans %}

{% csrf_token %} diff --git a/core/views/__init__.py b/core/views/__init__.py index 700ba698..f866fe97 100644 --- a/core/views/__init__.py +++ b/core/views/__init__.py @@ -8,8 +8,11 @@ from django.contrib.auth.forms import AuthenticationForm from core.models import Group def forbidden(request): - return HttpResponseForbidden(render(request, "core/403.jinja", context={'next': request.path, 'form': - AuthenticationForm(), 'popup': request.resolver_match.kwargs['popup'] or ""})) + try: + return HttpResponseForbidden(render(request, "core/403.jinja", context={'next': request.path, 'form': + AuthenticationForm(), 'popup': request.resolver_match.kwargs['popup'] or ""})) + except: + return HttpResponseForbidden(render(request, "core/403.jinja", context={'next': request.path, 'form': AuthenticationForm()})) def not_found(request): return HttpResponseNotFound(render(request, "core/404.jinja")) diff --git a/core/views/files.py b/core/views/files.py index 7a0d4d9d..cade3453 100644 --- a/core/views/files.py +++ b/core/views/files.py @@ -37,7 +37,7 @@ def send_file(request, file_id): response['Content-Disposition'] = 'inline; filename="%s"' % f.name return response -class AddFileForm(forms.Form): +class AddFilesForm(forms.Form): folder_name = forms.CharField(label=_("Add a new folder"), max_length=30, required=False) file_field = forms.FileField(widget=forms.ClearableFileInput(attrs={'multiple': True}), label=_("Files"), required=False) @@ -128,7 +128,7 @@ class FileView(CanViewMixin, DetailView, FormMixin): pk_url_kwarg = "file_id" template_name = 'core/file_detail.jinja' context_object_name = "file" - form_class = AddFileForm + form_class = AddFilesForm def get(self, request, *args, **kwargs): self.form = self.get_form() diff --git a/core/views/forms.py b/core/views/forms.py index 50de9275..6e2fcaf4 100644 --- a/core/views/forms.py +++ b/core/views/forms.py @@ -1,11 +1,56 @@ from django.contrib.auth.forms import UserCreationForm, AuthenticationForm, UserChangeForm from django import forms +from django.db import transaction +from django.core.exceptions import ValidationError from django.contrib.auth import logout, login, authenticate -from django.forms import CheckboxSelectMultiple, Select +from django.forms import CheckboxSelectMultiple, Select, DateInput, TextInput from django.utils.translation import ugettext as _ import logging -from core.models import User, Page, RealGroup +from core.models import User, Page, RealGroup, SithFile + +# Widgets + +class SelectSingle(Select): + def render(self, name, value, attrs=None): + if attrs: + attrs['class'] = "select_single" + else: + attrs = {'class': "select_single"} + return super(SelectSingle, self).render(name, value, attrs) + +class SelectMultiple(Select): + def render(self, name, value, attrs=None): + if attrs: + attrs['class'] = "select_multiple" + else: + attrs = {'class': "select_multiple"} + return super(SelectMultiple, self).render(name, value, attrs) + +class SelectDate(DateInput): + def render(self, name, value, attrs=None): + if attrs: + attrs['class'] = "select_date" + else: + attrs = {'class': "select_date"} + return super(SelectDate, self).render(name, value, attrs) + +class SelectFile(TextInput): + def render(self, name, value, attrs=None): + if attrs: + attrs['class'] = "select_file" + else: + attrs = {'class': "select_file"} + output = '%(content)s
' % { + 'content': super(SelectFile, self).render(name, value, attrs), + 'title': _("Choose file"), + 'name': name, + } + output += '' + _("Choose file") + '' + print(output) + return output + +# Forms class RegisteringForm(UserCreationForm): error_css_class = 'error' @@ -22,6 +67,69 @@ class RegisteringForm(UserCreationForm): user.save() return user +class UserProfileForm(forms.ModelForm): + """ + Form handling the user profile, managing the files + This form is actually pretty bad and was made in the rush before the migration. It should be refactored. + TODO: refactor this form + """ + class Meta: + model = User + fields = ['first_name', 'last_name', 'nick_name', 'email', 'date_of_birth', 'profile_pict', 'avatar_pict', + 'scrub_pict', 'sex', 'tshirt_size', 'role', 'department', 'dpt_option', 'semester', 'quote', 'school', + 'promo', 'forum_signature'] + widgets = { + 'date_of_birth': SelectDate, + 'profile_pict': forms.ClearableFileInput, + 'avatar_pict': forms.ClearableFileInput, + 'scrub_pict': forms.ClearableFileInput, + } + labels = { + 'profile_pict': _("Profile: you need to be visible on the picture, in order to be recognized (e.g. by the barmen)"), + 'avatar_pict': _("Avatar: used on the forum"), + 'scrub_pict': _("Scrub: let other know how your scrub looks like!"), + } + + def __init__(self, *arg, **kwargs): + super(UserProfileForm, self).__init__(*arg, **kwargs) + + def full_clean(self): + super(UserProfileForm, self).full_clean() + + def generate_name(self, field_name, f): + field_name = field_name[:-4] + return field_name + str(self.instance.id) + "." + f.content_type.split('/')[-1] + + def process(self, files): + avatar = self.instance.avatar_pict + profile = self.instance.profile_pict + scrub = self.instance.scrub_pict + self.full_clean() + self.cleaned_data['avatar_pict'] = avatar + self.cleaned_data['profile_pict'] = profile + self.cleaned_data['scrub_pict'] = scrub + parent = SithFile.objects.filter(parent=None, name="profiles").first() + for field,f in files: + with transaction.atomic(): + new_file = SithFile(parent=parent, name=self.generate_name(field, f), file=f, owner=self.instance, is_folder=False, + mime_type=f.content_type, size=f._size) + try: + if not (f.content_type == "image/jpeg" or + f.content_type == "image/png" or + f.content_type == "image/gif"): + raise ValidationError(_("Bad image format, only jpeg, png, and gif are accepted")) + old = SithFile.objects.filter(parent=parent, name=new_file.name).first() + if old: + old.delete() + new_file.clean() + new_file.save() + self.cleaned_data[field] = new_file + self._errors.pop(field, None) + except ValidationError as e: + self._errors.pop(field, None) + self.add_error(field, _("Error uploading file %(file_name)s: %(msg)s") % + {'file_name': f, 'msg': str(e.message)}) + self._post_clean() class UserPropForm(forms.ModelForm): error_css_class = 'error' @@ -52,13 +160,3 @@ class PagePropForm(forms.ModelForm): self.fields['edit_groups'].required = False self.fields['view_groups'].required = False -class SelectFile(Select): - def render(self, name, value, attrs=None): - output = '%(content)s' % { - 'title': _("Choose file"), - 'content': super(SelectFile, self).render(name, value, attrs), - } - output += '' + _("Choose file") + '' - print(output) - return output - diff --git a/core/views/user.py b/core/views/user.py index 76d98e55..95da12a4 100644 --- a/core/views/user.py +++ b/core/views/user.py @@ -11,7 +11,7 @@ from django.conf import settings import logging from core.views import CanViewMixin, CanEditMixin, CanEditPropMixin -from core.views.forms import RegisteringForm, UserPropForm +from core.views.forms import RegisteringForm, UserPropForm, UserProfileForm from core.models import User def login(request): @@ -115,7 +115,31 @@ class UserUpdateProfileView(CanEditMixin, UpdateView): model = User pk_url_kwarg = "user_id" template_name = "core/user_edit.jinja" - fields = ('first_name', 'last_name', 'nick_name', 'email', 'date_of_birth', ) + form_class = UserProfileForm + + def get(self, request, *args, **kwargs): + self.object = self.get_object() + self.form = self.get_form() + if self.form.instance.profile_pict and not request.user.is_in_group(settings.SITH_MAIN_BOARD_GROUP): + self.form.fields.pop('profile_pict', None) + return self.render_to_response(self.get_context_data(form=self.form)) + + def post(self, request, *args, **kwargs): + self.object = self.get_object() + self.form = self.get_form() + if self.form.instance.profile_pict and not request.user.is_in_group(settings.SITH_MAIN_BOARD_GROUP): + self.form.fields.pop('profile_pict', None) + files = request.FILES.items() + self.form.process(files) + if request.user.is_authenticated() and request.user.can_edit(self.object) and self.form.is_valid(): + return super(UserUpdateProfileView, self).form_valid(self.form) + return self.form_invalid(self.form) + + def get_context_data(self, **kwargs): + kwargs = super(UserUpdateProfileView, self).get_context_data(**kwargs) + kwargs['profile'] = self.form.instance + kwargs['form'] = self.form + return kwargs class UserUpdateGroupView(CanEditPropMixin, UpdateView): """ diff --git a/locale/fr/LC_MESSAGES/django.mo b/locale/fr/LC_MESSAGES/django.mo index e8894b59..073a64d0 100644 Binary files a/locale/fr/LC_MESSAGES/django.mo and b/locale/fr/LC_MESSAGES/django.mo differ diff --git a/locale/fr/LC_MESSAGES/django.po b/locale/fr/LC_MESSAGES/django.po index 35462c24..0b473e7c 100644 --- a/locale/fr/LC_MESSAGES/django.po +++ b/locale/fr/LC_MESSAGES/django.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2016-08-10 05:00+0200\n" +"POT-Creation-Date: 2016-08-11 04:02+0200\n" "PO-Revision-Date: 2016-07-18\n" "Last-Translator: Skia \n" "Language-Team: AE info \n" @@ -40,12 +40,12 @@ msgstr "numero de compte" msgid "%(club_account)s on %(bank_account)s" msgstr "%(club_account)s sur %(bank_account)s" -#: accounting/models.py:109 club/models.py:112 counter/models.py:268 +#: accounting/models.py:109 club/models.py:147 counter/models.py:268 #: launderette/models.py:112 msgid "start date" msgstr "date de début" -#: accounting/models.py:110 club/models.py:113 counter/models.py:269 +#: accounting/models.py:110 club/models.py:148 counter/models.py:269 msgid "end date" msgstr "date de fin" @@ -66,8 +66,9 @@ msgstr "montant effectif" msgid "number" msgstr "numéro" -#: accounting/models.py:154 core/models.py:560 counter/models.py:209 -#: counter/models.py:244 eboutic/models.py:13 eboutic/models.py:46 +#: accounting/models.py:154 core/models.py:390 core/models.py:666 +#: counter/models.py:209 counter/models.py:244 eboutic/models.py:13 +#: eboutic/models.py:46 msgid "date" msgstr "date" @@ -121,7 +122,7 @@ msgstr "Compte" msgid "Company" msgstr "Entreprise" -#: accounting/models.py:163 sith/settings.py:260 sith/settings_sample.py:260 +#: accounting/models.py:163 sith/settings.py:263 sith/settings_sample.py:263 msgid "Other" msgstr "Autre" @@ -205,7 +206,7 @@ msgstr "Nouveau compte club" #: accounting/templates/accounting/bank_account_list.jinja:15 #: accounting/templates/accounting/club_account_details.jinja:44 #: accounting/templates/accounting/journal_details.jinja:62 -#: club/templates/club/club_detail.jinja:7 core/templates/core/file.jinja:46 +#: club/templates/club/club_detail.jinja:7 core/templates/core/file.jinja:38 #: core/templates/core/page.jinja:31 core/templates/core/user_base.jinja:8 #: core/templates/core/user_tools.jinja:37 #: counter/templates/counter/counter_list.jinja:15 @@ -216,7 +217,7 @@ msgstr "Éditer" #: accounting/templates/accounting/bank_account_details.jinja:19 #: accounting/templates/accounting/bank_account_list.jinja:16 -#: core/templates/core/file_detail.jinja:38 +#: core/templates/core/file_detail.jinja:43 #: core/templates/core/group_list.jinja:13 #: launderette/templates/launderette/launderette_admin.jinja:16 #: launderette/views.py:146 @@ -296,7 +297,7 @@ msgid "No" msgstr "Non" #: accounting/templates/accounting/club_account_details.jinja:43 -#: core/templates/core/file.jinja:44 core/templates/core/page.jinja:28 +#: core/templates/core/file.jinja:36 core/templates/core/page.jinja:28 msgid "View" msgstr "Voir" @@ -381,37 +382,45 @@ msgstr "Un club avec ce nom UNIX existe déjà." msgid "address" msgstr "Adresse" -#: club/models.py:45 +#: club/models.py:38 core/models.py:112 +msgid "home" +msgstr "home" + +#: club/models.py:46 msgid "You can not make loops in clubs" msgstr "Vous ne pouvez pas faire de boucles dans les clubs" -#: club/models.py:110 eboutic/models.py:12 eboutic/models.py:45 +#: club/models.py:60 +msgid "A club with that unix_name already exists" +msgstr "Un club avec ce nom UNIX existe déjà." + +#: club/models.py:145 eboutic/models.py:12 eboutic/models.py:45 #: launderette/models.py:81 launderette/models.py:116 msgid "user" msgstr "nom d'utilisateur" -#: club/models.py:111 +#: club/models.py:146 msgid "club" msgstr "club" -#: club/models.py:114 +#: club/models.py:149 core/models.py:127 msgid "role" msgstr "rôle" -#: club/models.py:116 core/models.py:27 counter/models.py:53 +#: club/models.py:151 core/models.py:28 counter/models.py:53 #: counter/models.py:78 msgid "description" msgstr "description" -#: club/models.py:121 +#: club/models.py:156 msgid "User must be subscriber to take part to a club" msgstr "L'utilisateur doit être cotisant pour faire partie d'un club" -#: club/models.py:123 +#: club/models.py:158 msgid "User is already member of that club" msgstr "L'utilisateur est déjà membre de ce club" -#: club/models.py:127 +#: club/models.py:162 msgid "past member" msgstr "Anciens membres" @@ -420,7 +429,7 @@ msgstr "Anciens membres" msgid "Back to list" msgstr "Retour à la liste" -#: club/templates/club/club_detail.jinja:10 core/templates/core/file.jinja:49 +#: club/templates/club/club_detail.jinja:10 core/templates/core/file.jinja:41 #: core/templates/core/page.jinja:34 msgid "Prop" msgstr "Propriétés" @@ -435,7 +444,7 @@ msgstr "Éditer le club" #: club/templates/club/club_edit.jinja:8 #: club/templates/club/club_edit_prop.jinja:8 -#: core/templates/core/create.jinja:8 core/templates/core/edit.jinja:8 +#: core/templates/core/create.jinja:8 core/templates/core/edit.jinja:12 #: core/templates/core/file_edit.jinja:8 core/templates/core/page_prop.jinja:8 #: core/templates/core/pagerev_edit.jinja:24 #: counter/templates/counter/counter_edit.jinja:8 @@ -463,7 +472,8 @@ msgstr "Il n'y a pas de club dans ce site web." msgid "Club members" msgstr "Membres du club" -#: club/templates/club/club_members.jinja:13 launderette/views.py:146 +#: club/templates/club/club_members.jinja:13 +#: core/templates/core/file_detail.jinja:19 launderette/views.py:146 msgid "Add" msgstr "Ajouter" @@ -476,25 +486,30 @@ msgstr "Outils club" msgid "Counters:" msgstr "Comptoirs : " -#: core/models.py:23 +#: core/models.py:24 msgid "meta group status" msgstr "status du meta-groupe" -#: core/models.py:25 +#: core/models.py:26 msgid "Whether a group is a meta group or not" msgstr "Si un groupe est un meta-groupe ou pas" -#: core/models.py:60 +#: core/models.py:54 +#, python-format +msgid "%(value)s is not a valid promo (between 0 and %(end)s)" +msgstr "%(value)s n'est pas une promo valide (doit être entre 0 et %(end)s)" + +#: core/models.py:70 msgid "username" msgstr "nom d'utilisateur" -#: core/models.py:63 +#: core/models.py:73 msgid "Required. 254 characters or fewer. Letters, digits and @/./+/-/_ only." msgstr "" "Requis. Pas plus de 254 caractères. Uniquement des lettres, numéros, et @/./" "+/-/_" -#: core/models.py:67 +#: core/models.py:77 msgid "" "Enter a valid username. This value may contain only letters, numbers and @/./" "+/-/_ characters." @@ -502,39 +517,43 @@ msgstr "" "Entrez un nom d'utilisateur correct. Uniquement des lettres, numéros, et @/./" "+/-/_" -#: core/models.py:72 +#: core/models.py:82 msgid "A user with that username already exists." msgstr "Un utilisateur de ce nom existe déjà" -#: core/models.py:75 +#: core/models.py:85 msgid "first name" msgstr "Prénom" -#: core/models.py:76 +#: core/models.py:86 msgid "last name" msgstr "Nom" -#: core/models.py:77 +#: core/models.py:87 msgid "email address" msgstr "adresse email" -#: core/models.py:78 +#: core/models.py:88 msgid "date of birth" msgstr "date de naissance" -#: core/models.py:81 +#: core/models.py:89 +msgid "nick name" +msgstr "surnom" + +#: core/models.py:91 msgid "staff status" msgstr "status \"staff\"" -#: core/models.py:83 +#: core/models.py:93 msgid "Designates whether the user can log into this admin site." msgstr "Est-ce que l'utilisateur peut se logger à la partie admin du site." -#: core/models.py:86 +#: core/models.py:96 msgid "active" msgstr "actif" -#: core/models.py:89 +#: core/models.py:99 msgid "" "Designates whether this user should be treated as active. Unselect this " "instead of deleting accounts." @@ -542,121 +561,293 @@ msgstr "" "Est-ce que l'utilisateur doit être traité comme actif. Déselectionnez au " "lieu de supprimer les comptes." -#: core/models.py:93 +#: core/models.py:103 msgid "date joined" msgstr "date d'inscription" -#: core/models.py:95 +#: core/models.py:105 msgid "superuser" msgstr "super-utilisateur" -#: core/models.py:98 +#: core/models.py:108 msgid "Designates whether this user is a superuser. " msgstr "Est-ce que l'utilisateur est super-utilisateur." -#: core/models.py:280 +#: core/models.py:113 +msgid "profile" +msgstr "profil" + +#: core/models.py:114 +msgid "avatar" +msgstr "avatar" + +#: core/models.py:115 +msgid "scrub" +msgstr "blouse" + +#: core/models.py:116 +msgid "sex" +msgstr "sexe" + +#: core/models.py:116 +msgid "Man" +msgstr "Homme" + +#: core/models.py:116 +msgid "Woman" +msgstr "Femme" + +#: core/models.py:117 +msgid "tshirt size" +msgstr "taille de tshirt" + +#: core/models.py:118 +msgid "-" +msgstr "-" + +#: core/models.py:119 +msgid "XS" +msgstr "XS" + +#: core/models.py:120 +msgid "S" +msgstr "S" + +#: core/models.py:121 +msgid "M" +msgstr "M" + +#: core/models.py:122 +msgid "L" +msgstr "L" + +#: core/models.py:123 +msgid "XL" +msgstr "XL" + +#: core/models.py:124 +msgid "XXL" +msgstr "XXL" + +#: core/models.py:125 +msgid "XXXL" +msgstr "XXXL" + +#: core/models.py:128 +msgid "Student" +msgstr "Étudiant" + +#: core/models.py:129 +msgid "Administrative agent" +msgstr "Personnel administratif" + +#: core/models.py:130 +msgid "Teacher" +msgstr "Enseignant" + +#: core/models.py:131 +msgid "Agent" +msgstr "Personnel" + +#: core/models.py:132 +msgid "Doctor" +msgstr "Doctorant" + +#: core/models.py:133 +msgid "Former student" +msgstr "Ancien étudiant" + +#: core/models.py:134 +msgid "Service" +msgstr "Service" + +#: core/models.py:136 +msgid "department" +msgstr "département" + +#: core/models.py:137 +msgid "TC" +msgstr "TC" + +#: core/models.py:138 +msgid "IMSI" +msgstr "IMSI" + +#: core/models.py:139 +msgid "IMAP" +msgstr "IMAP" + +#: core/models.py:140 +msgid "INFO" +msgstr "INFO" + +#: core/models.py:141 +msgid "GI" +msgstr "GI" + +#: core/models.py:142 +msgid "E" +msgstr "E" + +#: core/models.py:143 +msgid "EE" +msgstr "EE" + +#: core/models.py:144 +msgid "GESC" +msgstr "GESC" + +#: core/models.py:145 +msgid "GMC" +msgstr "GMC" + +#: core/models.py:146 +msgid "MC" +msgstr "MC" + +#: core/models.py:147 +msgid "EDIM" +msgstr "EDIM" + +#: core/models.py:148 +msgid "Humanities" +msgstr "Humanités" + +#: core/models.py:149 +msgid "N/A" +msgstr "N/A" + +#: core/models.py:151 +msgid "dpt option" +msgstr "Filière" + +#: core/models.py:152 +msgid "semester" +msgstr "semestre" + +#: core/models.py:153 +msgid "quote" +msgstr "citation" + +#: core/models.py:154 +msgid "school" +msgstr "école" + +#: core/models.py:155 +msgid "promo" +msgstr "promo" + +#: core/models.py:156 +msgid "forum signature" +msgstr "signature du forum" + +#: core/models.py:240 +msgid "A user with that username already exists" +msgstr "Un utilisateur de ce nom d'utilisateur existe déjà" + +#: core/models.py:367 msgid "Visitor" msgstr "Visiteur" -#: core/models.py:285 +#: core/models.py:372 msgid "define if we show a users stats" msgstr "Definit si l'on montre les statistiques de l'utilisateur" -#: core/models.py:287 +#: core/models.py:374 msgid "Show your account statistics to others" msgstr "Montrez vos statistiques de compte aux autres" -#: core/models.py:294 +#: core/models.py:381 msgid "file name" msgstr "nom du fichier" -#: core/models.py:295 core/models.py:409 +#: core/models.py:382 core/models.py:515 msgid "parent" msgstr "parent" -#: core/models.py:296 core/models.py:305 +#: core/models.py:383 core/models.py:393 msgid "file" msgstr "fichier" -#: core/models.py:297 +#: core/models.py:384 msgid "owner" msgstr "propriétaire" -#: core/models.py:298 core/models.py:415 +#: core/models.py:385 core/models.py:521 msgid "edit group" msgstr "groupe d'édition" -#: core/models.py:299 core/models.py:416 +#: core/models.py:386 core/models.py:522 msgid "view group" msgstr "groupe de vue" -#: core/models.py:300 +#: core/models.py:387 msgid "is folder" msgstr "est un dossier" -#: core/models.py:301 +#: core/models.py:388 msgid "mime type" msgstr "type mime" -#: core/models.py:302 +#: core/models.py:389 msgid "size" msgstr "taille" -#: core/models.py:316 +#: core/models.py:419 msgid "Character '/' not authorized in name" msgstr "Le caractère '/' n'est pas autorisé dans les noms de fichier" -#: core/models.py:319 core/models.py:324 +#: core/models.py:422 core/models.py:427 msgid "Loop in folder tree" msgstr "Boucle dans l'arborescence des dossiers" -#: core/models.py:328 +#: core/models.py:431 msgid "You can not make a file be a children of a non folder file" msgstr "" "Vous ne pouvez pas mettre un fichier enfant de quelque chose qui n'est pas " "un dossier" -#: core/models.py:332 +#: core/models.py:435 msgid "Duplicate file" msgstr "Un fichier de ce nom existe déjà" -#: core/models.py:342 +#: core/models.py:445 msgid "You must provide a file" msgstr "Vous devez fournir un fichier" -#: core/models.py:367 +#: core/models.py:470 msgid "Folder: " msgstr "Dossier : " -#: core/models.py:369 +#: core/models.py:472 msgid "File: " msgstr "Fichier : " -#: core/models.py:408 core/models.py:412 +#: core/models.py:514 core/models.py:518 msgid "page name" msgstr "nom de la page" -#: core/models.py:413 +#: core/models.py:519 msgid "owner group" msgstr "groupe propriétaire" -#: core/models.py:444 +#: core/models.py:550 msgid "Duplicate page" msgstr "Une page de ce nom existe déjà" -#: core/models.py:450 +#: core/models.py:556 msgid "Loop in page tree" msgstr "Boucle dans l'arborescence des pages" -#: core/models.py:557 +#: core/models.py:663 msgid "revision" msgstr "révision" -#: core/models.py:558 +#: core/models.py:664 msgid "page title" msgstr "titre de la page" -#: core/models.py:559 +#: core/models.py:665 msgid "page content" msgstr "contenu de la page" @@ -672,48 +863,48 @@ msgstr "404. Non trouvé" msgid "Welcome!" msgstr "Bienvenue!" -#: core/templates/core/base.jinja:17 +#: core/templates/core/base.jinja:18 msgid "Logo" msgstr "Logo" -#: core/templates/core/base.jinja:20 core/templates/core/login.jinja:4 +#: core/templates/core/base.jinja:21 core/templates/core/login.jinja:4 #: core/templates/core/password_reset_complete.jinja:5 msgid "Login" msgstr "Connexion" -#: core/templates/core/base.jinja:21 core/templates/core/register.jinja:18 +#: core/templates/core/base.jinja:22 core/templates/core/register.jinja:18 msgid "Register" msgstr "S'enregister" -#: core/templates/core/base.jinja:24 +#: core/templates/core/base.jinja:25 msgid "Tools" msgstr "Outils" -#: core/templates/core/base.jinja:25 +#: core/templates/core/base.jinja:26 msgid "Logout" msgstr "Déconnexion" -#: core/templates/core/base.jinja:31 +#: core/templates/core/base.jinja:36 msgid "Users" msgstr "Utilisateurs" -#: core/templates/core/base.jinja:32 +#: core/templates/core/base.jinja:37 msgid "Wiki" msgstr "Wiki" -#: core/templates/core/base.jinja:33 +#: core/templates/core/base.jinja:38 msgid "Pages" msgstr "Pages" -#: core/templates/core/base.jinja:34 +#: core/templates/core/base.jinja:39 msgid "Clubs" msgstr "Clubs" -#: core/templates/core/base.jinja:35 +#: core/templates/core/base.jinja:40 msgid "Services" msgstr "Services" -#: core/templates/core/base.jinja:49 +#: core/templates/core/base.jinja:55 msgid "Site made by good people" msgstr "Site réalisé par des gens biens" @@ -723,24 +914,29 @@ msgid "Create %(name)s" msgstr "Créer %(name)s" #: core/templates/core/delete_confirm.jinja:4 +#: core/templates/core/file_delete_confirm.jinja:4 msgid "Delete confirmation" msgstr "Confirmation de suppression" #: core/templates/core/delete_confirm.jinja:6 +#: core/templates/core/file_delete_confirm.jinja:6 #, python-format msgid "Are you sure you want to delete \"%(obj)s\"?" msgstr "Êtes-vous sûr de vouloir supprimer \"%(obj)s\" ?" #: core/templates/core/delete_confirm.jinja:7 +#: core/templates/core/file_delete_confirm.jinja:7 msgid "Confirm" msgstr "Confirmation" #: core/templates/core/delete_confirm.jinja:8 +#: core/templates/core/file_delete_confirm.jinja:8 #: counter/templates/counter/counter_click.jinja:71 msgid "Cancel" msgstr "Annuler" -#: core/templates/core/edit.jinja:4 core/templates/core/file_edit.jinja:4 +#: core/templates/core/edit.jinja:4 core/templates/core/edit.jinja.py:8 +#: core/templates/core/file_edit.jinja:4 #, python-format msgid "Edit %(obj)s" msgstr "Éditer %(obj)s" @@ -757,35 +953,39 @@ msgstr "Nouveau fichier" msgid "Not found" msgstr "Non trouvé" -#: core/templates/core/file.jinja:20 core/views/files.py:103 +#: core/templates/core/file.jinja:20 core/views/files.py:42 msgid "Files" msgstr "Fichiers" -#: core/templates/core/file_detail.jinja:15 +#: core/templates/core/file.jinja:32 +msgid "My files" +msgstr "Mes fichiers" + +#: core/templates/core/file_detail.jinja:13 msgid "Owner: " msgstr "Propriétaire : " -#: core/templates/core/file_detail.jinja:20 -msgid "Upload" -msgstr "Téléverser" - #: core/templates/core/file_detail.jinja:34 msgid "Real name: " msgstr "Nom réel : " #: core/templates/core/file_detail.jinja:35 +msgid "Date: " +msgstr "Date : " + +#: core/templates/core/file_detail.jinja:37 msgid "Type: " msgstr "Type : " -#: core/templates/core/file_detail.jinja:36 +#: core/templates/core/file_detail.jinja:38 msgid "Size: " msgstr "Taille : " -#: core/templates/core/file_detail.jinja:36 +#: core/templates/core/file_detail.jinja:38 msgid "bytes" msgstr "octets" -#: core/templates/core/file_detail.jinja:37 +#: core/templates/core/file_detail.jinja:40 msgid "Download" msgstr "Télécharger" @@ -797,7 +997,8 @@ msgstr "Il n'y a pas de fichier sur ce site web." msgid "Edit group" msgstr "Éditer le groupe" -#: core/templates/core/group_edit.jinja:9 core/templates/core/user_edit.jinja:8 +#: core/templates/core/group_edit.jinja:9 +#: core/templates/core/user_edit.jinja:20 #: core/templates/core/user_group.jinja:8 msgid "Update" msgstr "Mettre à jour" @@ -833,12 +1034,12 @@ msgstr "" msgid "Please login to see this page." msgstr "Merci de vous identifier pour voir cette page." -#: core/templates/core/login.jinja:26 +#: core/templates/core/login.jinja:28 #: counter/templates/counter/counter_main.jinja:48 msgid "login" msgstr "login" -#: core/templates/core/login.jinja:30 +#: core/templates/core/login.jinja:32 msgid "Lost password?" msgstr "Mot de passe perdu ?" @@ -1041,24 +1242,29 @@ msgstr "Groupes" msgid "%(user_name)s's profile" msgstr "Profil de %(user_name)s" -#: core/templates/core/user_detail.jinja:8 -msgid "User Profile" -msgstr "Profil de l'utilisateur" +#: core/templates/core/user_detail.jinja:12 +#: core/templates/core/user_edit.jinja:11 +msgid "Profile" +msgstr "Profil" -#: core/templates/core/user_detail.jinja:13 +#: core/templates/core/user_detail.jinja:17 msgid "Born: " msgstr "Né le : " #: core/templates/core/user_detail.jinja:20 +msgid "Option: " +msgstr "Filière : " + +#: core/templates/core/user_detail.jinja:29 #, python-format msgid "User is subscriber until %(subscription_end)s" msgstr "L'utilisateur est cotisant jusqu'au %(subscription_end)s" -#: core/templates/core/user_detail.jinja:22 +#: core/templates/core/user_detail.jinja:31 msgid "User is not subscribed. " msgstr "L'utilisateur n'est pas cotisant." -#: core/templates/core/user_detail.jinja:23 +#: core/templates/core/user_detail.jinja:32 #: subscription/templates/subscription/subscription.jinja:4 #: subscription/templates/subscription/subscription.jinja:8 msgid "New subscription" @@ -1068,7 +1274,35 @@ msgstr "Nouvelle cotisation" msgid "Edit user profile" msgstr "Éditer le profil de l'utilisateur" -#: core/templates/core/user_edit.jinja:11 +#: core/templates/core/user_edit.jinja:10 +msgid "Current profile: " +msgstr "Profil actuel : " + +#: core/templates/core/user_edit.jinja:13 +msgid "Current avatar: " +msgstr "Avatar actuel : " + +#: core/templates/core/user_edit.jinja:14 +msgid "Avatar" +msgstr "Avatar" + +#: core/templates/core/user_edit.jinja:16 +msgid "Current scrub: " +msgstr "Blouse actuelle : " + +#: core/templates/core/user_edit.jinja:17 +msgid "Scrub" +msgstr "Blouse" + +#: core/templates/core/user_edit.jinja:21 +msgid "Username: " +msgstr "Nom d'utilisateur : " + +#: core/templates/core/user_edit.jinja:23 +msgid "Account number: " +msgstr "Numero de compte : " + +#: core/templates/core/user_edit.jinja:26 msgid "Change my password" msgstr "Changer mon mot de passe" @@ -1134,15 +1368,44 @@ msgstr "Comptabilité générale" msgid "Club account: " msgstr "Compte club : " -#: core/views/files.py:134 +#: core/views/files.py:41 +msgid "Add a new folder" +msgstr "Ajouter un nouveau dossier" + +#: core/views/files.py:52 +#, python-format +msgid "Error creating folder %(folder_name)s: %(msg)s" +msgstr "Erreur de création du dossier %(folder_name)s : %(msg)s" + +#: core/views/files.py:62 core/views/forms.py:130 #, python-format msgid "Error uploading file %(file_name)s: %(msg)s" msgstr "Erreur d'envoie du fichier %(file_name)s : %(msg)s" -#: core/views/forms.py:58 core/views/forms.py:61 +#: core/views/forms.py:46 core/views/forms.py:49 msgid "Choose file" msgstr "Choisir un fichier" +#: core/views/forms.py:88 +msgid "" +"Profile: you need to be visible on the picture, in order to be recognized (e." +"g. by the barmen)" +msgstr "" +"Photo de profil: vous devez être visible sur la photo afin d'être reconnu " +"(par exemple par les barmen)" + +#: core/views/forms.py:89 +msgid "Avatar: used on the forum" +msgstr "Avatar : utilisé sur le forum" + +#: core/views/forms.py:90 +msgid "Scrub: let other know how your scrub looks like!" +msgstr "Blouse : montrez aux autres à quoi ressemble votre blouse !" + +#: core/views/forms.py:120 +msgid "Bad image format, only jpeg, png, and gif are accepted" +msgstr "Mauvais format d'image, seuls les jpeg, png, et gif sont acceptés" + #: counter/models.py:24 msgid "account id" msgstr "numéro de compte" @@ -1379,7 +1642,7 @@ msgstr "ANN" msgid "You have not enough money to buy all the basket" msgstr "Vous n'avez pas assez d'argent pour acheter le panier" -#: eboutic/models.py:47 sith/settings.py:254 sith/settings_sample.py:254 +#: eboutic/models.py:47 sith/settings.py:257 sith/settings_sample.py:257 msgid "Credit card" msgstr "Carte banquaire" @@ -1520,12 +1783,12 @@ msgid "Washing and drying" msgstr "Lavage et séchage" #: launderette/templates/launderette/launderette_book.jinja:26 -#: sith/settings.py:342 sith/settings_sample.py:342 +#: sith/settings.py:345 sith/settings_sample.py:345 msgid "Washing" msgstr "Lavage" #: launderette/templates/launderette/launderette_book.jinja:30 -#: sith/settings.py:342 sith/settings_sample.py:342 +#: sith/settings.py:345 sith/settings_sample.py:345 msgid "Drying" msgstr "Séchage" @@ -1580,83 +1843,83 @@ msgstr "L'utilisateur n'a pas réservé de créneau" msgid "Token not found" msgstr "Jeton non trouvé" -#: sith/settings.py:251 sith/settings.py:258 sith/settings.py:276 -#: sith/settings_sample.py:251 sith/settings_sample.py:258 -#: sith/settings_sample.py:276 +#: sith/settings.py:254 sith/settings.py:261 sith/settings.py:279 +#: sith/settings_sample.py:254 sith/settings_sample.py:261 +#: sith/settings_sample.py:279 msgid "Check" msgstr "Chèque" -#: sith/settings.py:252 sith/settings.py:259 sith/settings.py:277 -#: sith/settings_sample.py:252 sith/settings_sample.py:259 -#: sith/settings_sample.py:277 +#: sith/settings.py:255 sith/settings.py:262 sith/settings.py:280 +#: sith/settings_sample.py:255 sith/settings_sample.py:262 +#: sith/settings_sample.py:280 msgid "Cash" msgstr "Espèces" -#: sith/settings.py:253 sith/settings_sample.py:253 +#: sith/settings.py:256 sith/settings_sample.py:256 msgid "Transfert" msgstr "Virement" -#: sith/settings.py:264 sith/settings_sample.py:264 +#: sith/settings.py:267 sith/settings_sample.py:267 msgid "Belfort" msgstr "Belfort" -#: sith/settings.py:265 sith/settings_sample.py:265 +#: sith/settings.py:268 sith/settings_sample.py:268 msgid "Sevenans" msgstr "Sevenans" -#: sith/settings.py:266 sith/settings_sample.py:266 +#: sith/settings.py:269 sith/settings_sample.py:269 msgid "Montbéliard" msgstr "Montbéliard" -#: sith/settings.py:290 sith/settings_sample.py:290 +#: sith/settings.py:293 sith/settings_sample.py:293 msgid "One semester" msgstr "Un semestre" -#: sith/settings.py:295 sith/settings_sample.py:295 +#: sith/settings.py:298 sith/settings_sample.py:298 msgid "Two semesters" msgstr "Deux semestres" -#: sith/settings.py:300 sith/settings_sample.py:300 +#: sith/settings.py:303 sith/settings_sample.py:303 msgid "Common core cursus" msgstr "Cursus tronc commun" -#: sith/settings.py:305 sith/settings_sample.py:305 +#: sith/settings.py:308 sith/settings_sample.py:308 msgid "Branch cursus" msgstr "Cursus branche" -#: sith/settings.py:313 sith/settings_sample.py:313 +#: sith/settings.py:316 sith/settings_sample.py:316 msgid "President" msgstr "Président" -#: sith/settings.py:314 sith/settings_sample.py:314 +#: sith/settings.py:317 sith/settings_sample.py:317 msgid "Vice-President" msgstr "Vice-Président" -#: sith/settings.py:315 sith/settings_sample.py:315 +#: sith/settings.py:318 sith/settings_sample.py:318 msgid "Treasurer" msgstr "Trésorier" -#: sith/settings.py:316 sith/settings_sample.py:316 +#: sith/settings.py:319 sith/settings_sample.py:319 msgid "Communication supervisor" msgstr "Responsable com" -#: sith/settings.py:317 sith/settings_sample.py:317 +#: sith/settings.py:320 sith/settings_sample.py:320 msgid "Secretary" msgstr "Secrétaire" -#: sith/settings.py:318 sith/settings_sample.py:318 +#: sith/settings.py:321 sith/settings_sample.py:321 msgid "IT supervisor" msgstr "Responsable info" -#: sith/settings.py:319 sith/settings_sample.py:319 +#: sith/settings.py:322 sith/settings_sample.py:322 msgid "Board member" msgstr "Membre du bureau" -#: sith/settings.py:320 sith/settings_sample.py:320 +#: sith/settings.py:323 sith/settings_sample.py:323 msgid "Active member" msgstr "Membre actif" -#: sith/settings.py:321 sith/settings_sample.py:321 +#: sith/settings.py:324 sith/settings_sample.py:324 msgid "Curious" msgstr "Curieux" @@ -1696,3 +1959,6 @@ msgstr "Un utilisateur avec cette adresse email existe déjà" msgid "You must either choose an existing user or create a new one properly" msgstr "" "Vous devez soit choisir un utilisateur existant, ou en créer un proprement." + +#~ msgid "User Profile" +#~ msgstr "Profil de l'utilisateur" diff --git a/sith/settings_sample.py b/sith/settings_sample.py index 274e975f..8b004e2a 100644 --- a/sith/settings_sample.py +++ b/sith/settings_sample.py @@ -214,6 +214,9 @@ SITH_LAUNDERETTE_MANAGER = { # (month, day) SITH_START_DATE = (8, 15) # 15th August +# Used to determine the valid promos +SITH_SCHOOL_START_YEAR = 1999 + SITH_GROUPS = { 'root': { 'id': 1,