Commit c0a66f9a authored by Skia's avatar Skia
Browse files

Finish profile of users

parent 5113d8fd
...@@ -32,7 +32,7 @@ class Command(BaseCommand): ...@@ -32,7 +32,7 @@ class Command(BaseCommand):
for g in settings.SITH_GROUPS.values(): for g in settings.SITH_GROUPS.values():
Group(id=g['id'], name=g['name']).save() Group(id=g['id'], name=g['name']).save()
self.reset_index("core", "auth") self.reset_index("core", "auth")
root = User(username='root', last_name="", first_name="Bibou", root = User(id=0, username='root', last_name="", first_name="Bibou",
email="ae.info@utbm.fr", email="ae.info@utbm.fr",
date_of_birth="1942-06-12", date_of_birth="1942-06-12",
is_superuser=True, is_staff=True) is_superuser=True, is_staff=True)
...@@ -76,6 +76,19 @@ class Command(BaseCommand): ...@@ -76,6 +76,19 @@ class Command(BaseCommand):
p.save() p.save()
PageRev(page=p, title="Wiki index", author=root, content=""" PageRev(page=p, title="Wiki index", author=root, content="""
Welcome to the wiki page! Welcome to the wiki page!
""").save()
p = Page(name="services")
p.set_lock(root)
p.save()
p.view_groups=[settings.SITH_GROUPS['public']['id']]
p.set_lock(root)
PageRev(page=p, title="Services", author=root, content="""
| | | |
| :---: | :---: | :---: | :---: |
| [Eboutic](/eboutic) | [Laverie](/launderette) | Matmat | [Fichiers](/file) |
| SAS | Weekmail | Forum | |
""").save() """).save()
p = Page(name="launderette") p = Page(name="launderette")
......
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
import phonenumber_field.modelfields
from django.utils.timezone import utc
import datetime
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('core', '0006_auto_20160811_0450'),
]
operations = [
migrations.AddField(
model_name='user',
name='address',
field=models.CharField(default='', verbose_name='address', max_length=128, blank=True),
),
migrations.AddField(
model_name='user',
name='last_update',
field=models.DateField(default=datetime.datetime(2016, 8, 13, 3, 22, 21, 699918, tzinfo=utc), verbose_name='last update', auto_now=True),
preserve_default=False,
),
migrations.AddField(
model_name='user',
name='parent_address',
field=models.CharField(default='', verbose_name='parent address', max_length=128, blank=True),
),
migrations.AddField(
model_name='user',
name='parent_phone',
field=phonenumber_field.modelfields.PhoneNumberField(blank=True, verbose_name='parent phone', max_length=128, null=True),
),
migrations.AddField(
model_name='user',
name='phone',
field=phonenumber_field.modelfields.PhoneNumberField(blank=True, verbose_name='phone', max_length=128, null=True),
),
migrations.AddField(
model_name='user',
name='second_email',
field=models.EmailField(blank=True, verbose_name='second email address', max_length=254, null=True),
),
migrations.AlterField(
model_name='user',
name='avatar_pict',
field=models.OneToOneField(verbose_name='avatar', on_delete=django.db.models.deletion.SET_NULL, related_name='avatar_of', blank=True, to='core.SithFile', null=True),
),
migrations.AlterField(
model_name='user',
name='department',
field=models.CharField(default='NA', verbose_name='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'), ('HUMA', 'Humanities'), ('NA', 'N/A')], blank=True),
),
migrations.AlterField(
model_name='user',
name='dpt_option',
field=models.CharField(default='', verbose_name='dpt option', max_length=32, blank=True),
),
migrations.AlterField(
model_name='user',
name='first_name',
field=models.CharField(verbose_name='first name', max_length=64),
),
migrations.AlterField(
model_name='user',
name='forum_signature',
field=models.TextField(default='', verbose_name='forum signature', max_length=256, blank=True),
),
migrations.AlterField(
model_name='user',
name='last_name',
field=models.CharField(verbose_name='last name', max_length=64),
),
migrations.AlterField(
model_name='user',
name='nick_name',
field=models.CharField(blank=True, verbose_name='nick name', max_length=64, null=True),
),
migrations.AlterField(
model_name='user',
name='profile_pict',
field=models.OneToOneField(verbose_name='profile', on_delete=django.db.models.deletion.SET_NULL, related_name='profile_of', blank=True, to='core.SithFile', null=True),
),
migrations.AlterField(
model_name='user',
name='quote',
field=models.CharField(default='', verbose_name='quote', max_length=256, blank=True),
),
migrations.AlterField(
model_name='user',
name='role',
field=models.CharField(default='', verbose_name='role', max_length=15, choices=[('STUDENT', 'Student'), ('ADMINISTRATIVE', 'Administrative agent'), ('TEACHER', 'Teacher'), ('AGENT', 'Agent'), ('DOCTOR', 'Doctor'), ('FORMER STUDENT', 'Former student'), ('SERVICE', 'Service')], blank=True),
),
migrations.AlterField(
model_name='user',
name='school',
field=models.CharField(default='', verbose_name='school', max_length=80, blank=True),
),
migrations.AlterField(
model_name='user',
name='scrub_pict',
field=models.OneToOneField(verbose_name='scrub', on_delete=django.db.models.deletion.SET_NULL, related_name='scrub_of', blank=True, to='core.SithFile', null=True),
),
migrations.AlterField(
model_name='user',
name='semester',
field=models.CharField(default='', verbose_name='semester', max_length=5, blank=True),
),
migrations.AlterField(
model_name='user',
name='tshirt_size',
field=models.CharField(default='-', verbose_name='tshirt size', max_length=5, choices=[('-', '-'), ('XS', 'XS'), ('S', 'S'), ('M', 'M'), ('L', 'L'), ('XL', 'XL'), ('XXL', 'XXL'), ('XXXL', 'XXXL')]),
),
]
...@@ -7,6 +7,8 @@ from django.core.exceptions import ValidationError ...@@ -7,6 +7,8 @@ from django.core.exceptions import ValidationError
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.conf import settings from django.conf import settings
from django.db import transaction from django.db import transaction
from phonenumber_field.modelfields import PhoneNumberField
from datetime import datetime, timedelta, date from datetime import datetime, timedelta, date
import unicodedata import unicodedata
...@@ -82,11 +84,11 @@ class User(AbstractBaseUser): ...@@ -82,11 +84,11 @@ class User(AbstractBaseUser):
'unique': _("A user with that username already exists."), 'unique': _("A user with that username already exists."),
}, },
) )
first_name = models.CharField(_('first name'), max_length=30) first_name = models.CharField(_('first name'), max_length=64)
last_name = models.CharField(_('last name'), max_length=30) last_name = models.CharField(_('last name'), max_length=64)
email = models.EmailField(_('email address'), unique=True) email = models.EmailField(_('email address'), unique=True)
date_of_birth = models.DateField(_('date of birth'), blank=True, null=True) date_of_birth = models.DateField(_('date of birth'), blank=True, null=True)
nick_name = models.CharField(_('nick name'), max_length=30, blank=True) nick_name = models.CharField(_('nick name'), max_length=64, null=True, blank=True)
is_staff = models.BooleanField( is_staff = models.BooleanField(
_('staff status'), _('staff status'),
default=False, default=False,
...@@ -101,6 +103,7 @@ class User(AbstractBaseUser): ...@@ -101,6 +103,7 @@ class User(AbstractBaseUser):
), ),
) )
date_joined = models.DateField(_('date joined'), auto_now_add=True) date_joined = models.DateField(_('date joined'), auto_now_add=True)
last_update = models.DateField(_('last update'), auto_now=True)
is_superuser = models.BooleanField( is_superuser = models.BooleanField(
_('superuser'), _('superuser'),
default=False, default=False,
...@@ -110,9 +113,12 @@ class User(AbstractBaseUser): ...@@ -110,9 +113,12 @@ class User(AbstractBaseUser):
) )
groups = models.ManyToManyField(RealGroup, related_name='users', blank=True) groups = models.ManyToManyField(RealGroup, related_name='users', blank=True)
home = models.OneToOneField('SithFile', related_name='home_of', verbose_name=_("home"), null=True, 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) profile_pict = models.OneToOneField('SithFile', related_name='profile_of', verbose_name=_("profile"), null=True,
avatar_pict = models.OneToOneField('SithFile', related_name='avatar_of', verbose_name=_("avatar"), null=True, blank=True) blank=True, on_delete=models.SET_NULL)
scrub_pict = models.OneToOneField('SithFile', related_name='scrub_of', verbose_name=_("scrub"), null=True, blank=True) avatar_pict = models.OneToOneField('SithFile', related_name='avatar_of', verbose_name=_("avatar"), null=True,
blank=True, on_delete=models.SET_NULL)
scrub_pict = models.OneToOneField('SithFile', related_name='scrub_of', verbose_name=_("scrub"), null=True,
blank=True, on_delete=models.SET_NULL)
sex = models.CharField(_("sex"), max_length=10, choices=[("MAN", _("Man")), ("WOMAN", _("Woman"))], default="MAN") sex = models.CharField(_("sex"), max_length=10, choices=[("MAN", _("Man")), ("WOMAN", _("Woman"))], default="MAN")
tshirt_size = models.CharField(_("tshirt size"), max_length=5, choices=[ tshirt_size = models.CharField(_("tshirt size"), max_length=5, choices=[
("-", _("-")), ("-", _("-")),
...@@ -123,7 +129,7 @@ class User(AbstractBaseUser): ...@@ -123,7 +129,7 @@ class User(AbstractBaseUser):
("XL", _("XL")), ("XL", _("XL")),
("XXL", _("XXL")), ("XXL", _("XXL")),
("XXXL", _("XXXL")), ("XXXL", _("XXXL")),
], default="M") ], default="-")
role = models.CharField(_("role"), max_length=15, choices=[ role = models.CharField(_("role"), max_length=15, choices=[
("STUDENT", _("Student")), ("STUDENT", _("Student")),
("ADMINISTRATIVE", _("Administrative agent")), ("ADMINISTRATIVE", _("Administrative agent")),
...@@ -132,7 +138,7 @@ class User(AbstractBaseUser): ...@@ -132,7 +138,7 @@ class User(AbstractBaseUser):
("DOCTOR", _("Doctor")), ("DOCTOR", _("Doctor")),
("FORMER STUDENT", _("Former student")), ("FORMER STUDENT", _("Former student")),
("SERVICE", _("Service")), ("SERVICE", _("Service")),
], default="STUDENT") ], blank=True, default="")
department = models.CharField(_("department"), max_length=15, choices=[ department = models.CharField(_("department"), max_length=15, choices=[
("TC", _("TC")), ("TC", _("TC")),
("IMSI", _("IMSI")), ("IMSI", _("IMSI")),
...@@ -145,16 +151,20 @@ class User(AbstractBaseUser): ...@@ -145,16 +151,20 @@ class User(AbstractBaseUser):
("GMC", _("GMC")), ("GMC", _("GMC")),
("MC", _("MC")), ("MC", _("MC")),
("EDIM", _("EDIM")), ("EDIM", _("EDIM")),
("HUMAN", _("Humanities")), ("HUMA", _("Humanities")),
("NA", _("N/A")), ("NA", _("N/A")),
], default="NA") ], default="NA", blank=True)
dpt_option = models.CharField(_("dpt option"), max_length=32, null=True, blank=True) dpt_option = models.CharField(_("dpt option"), max_length=32, blank=True, default="")
semester = models.CharField(_("semester"), max_length=5, null=True, blank=True) semester = models.CharField(_("semester"), max_length=5, blank=True, default="")
quote = models.CharField(_("quote"), max_length=64, null=True, blank=True) quote = models.CharField(_("quote"), max_length=256, blank=True, default="")
school = models.CharField(_("school"), max_length=32, null=True, blank=True) school = models.CharField(_("school"), max_length=80, blank=True, default="")
promo = models.IntegerField(_("promo"), validators=[validate_promo], null=True, blank=True) promo = models.IntegerField(_("promo"), validators=[validate_promo], null=True, blank=True)
forum_signature = models.TextField(_("forum signature"), max_length=256, null=True, blank=True) forum_signature = models.TextField(_("forum signature"), max_length=256, blank=True, default="")
# TODO: add phone numbers with https://github.com/stefanfoulis/django-phonenumber-field second_email = models.EmailField(_('second email address'), null=True, blank=True)
phone = PhoneNumberField(_("phone"), null=True, blank=True)
parent_phone = PhoneNumberField(_("parent phone"), null=True, blank=True)
address = models.CharField(_("address"), max_length=128, blank=True, default="")
parent_address = models.CharField(_("parent address"), max_length=128, blank=True, default="")
objects = UserManager() objects = UserManager()
...@@ -217,7 +227,7 @@ class User(AbstractBaseUser): ...@@ -217,7 +227,7 @@ class User(AbstractBaseUser):
with transaction.atomic(): with transaction.atomic():
if self.id: if self.id:
old = User.objects.filter(id=self.id).first() old = User.objects.filter(id=self.id).first()
if old.username != self.username: if old and old.username != self.username:
self._change_username(self.username) self._change_username(self.username)
super(User, self).save(*args, **kwargs) super(User, self).save(*args, **kwargs)
...@@ -263,8 +273,8 @@ class User(AbstractBaseUser): ...@@ -263,8 +273,8 @@ class User(AbstractBaseUser):
Returns the display name of the user. Returns the display name of the user.
A nickname if possible, otherwise, the full name A nickname if possible, otherwise, the full name
""" """
if self.nick_name != "": if self.nick_name:
return self.nick_name return "%s (%s)" % (self.get_full_name(), self.nick_name)
return self.get_full_name() return self.get_full_name()
def email_user(self, subject, message, from_email=None, **kwargs): def email_user(self, subject, message, from_email=None, **kwargs):
...@@ -463,7 +473,7 @@ class SithFile(models.Model): ...@@ -463,7 +473,7 @@ class SithFile(models.Model):
if attr == "is_file": if attr == "is_file":
return not self.is_folder return not self.is_folder
else: else:
return object.__getattribute__(self, attr) return super(SithFile, self).__getattribute__(attr)
def __str__(self): def __str__(self):
if self.is_folder: if self.is_folder:
......
...@@ -60,6 +60,7 @@ nav a:hover { ...@@ -60,6 +60,7 @@ nav a:hover {
margin: 0px auto; margin: 0px auto;
padding: 1em 1%; padding: 1em 1%;
background: white; background: white;
overflow: auto;
} }
h1, h2, h3, h4, h5, h6 { h1, h2, h3, h4, h5, h6 {
......
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
<a href="{{ url('core:page', page_name="Index") }}">{% trans %}Wiki{% endtrans %}</a> <a href="{{ url('core:page', page_name="Index") }}">{% trans %}Wiki{% endtrans %}</a>
<a href="{{ url('core:page_list') }}">{% trans %}Pages{% endtrans %}</a> <a href="{{ url('core:page_list') }}">{% trans %}Pages{% endtrans %}</a>
<a href="{{ url('club:club_list') }}">{% trans %}Clubs{% endtrans %}</a> <a href="{{ url('club:club_list') }}">{% trans %}Clubs{% endtrans %}</a>
<a href="{{ url('core:page', "Services") }}">{% trans %}Services{% endtrans %}</a> <a href="{{ url('core:page', "services") }}">{% trans %}Services{% endtrans %}</a>
</nav> </nav>
{% endif %} {% endif %}
{% endblock %} {% endblock %}
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
{% block content %} {% block content %}
<div class="tool-bar"> <div class="tool-bar">
<div>{{ profile.get_display_name() }}</div>
<div class="tools"> <div class="tools">
<a href="{{ url('core:user_profile', user_id=profile.id) }}">{% trans %}Infos{% endtrans %}</a> <a href="{{ url('core:user_profile', user_id=profile.id) }}">{% trans %}Infos{% endtrans %}</a>
{% if can_edit(profile, request.user) or user.id == profile.id %} {% if can_edit(profile, request.user) or user.id == profile.id %}
...@@ -16,7 +17,6 @@ ...@@ -16,7 +17,6 @@
<a href="{{ url('core:user_account', user_id=profile.id) }}">{% trans %}Account{% endtrans %}</a> <a href="{{ url('core:user_account', user_id=profile.id) }}">{% trans %}Account{% endtrans %}</a>
{% endif %} {% endif %}
</div> </div>
<h5>{{ profile.get_display_name() }}</h5>
</div> </div>
<hr> <hr>
......
{% extends "core/user_base.jinja" %} {% extends "core/user_base.jinja" %}
{% block title %}
{% trans %}Edit user{% endtrans %}
{% endblock %}
{% block infos %} {% block infos %}
<h2>{% trans %}Edit user profile{% endtrans %}</h2> <h2>{% trans %}Edit user profile{% endtrans %}</h2>
<form action="" method="post" enctype="multipart/form-data"> <form action="" method="post" enctype="multipart/form-data">
......
...@@ -5,10 +5,13 @@ from django.core.exceptions import ValidationError ...@@ -5,10 +5,13 @@ from django.core.exceptions import ValidationError
from django.contrib.auth import logout, login, authenticate from django.contrib.auth import logout, login, authenticate
from django.forms import CheckboxSelectMultiple, Select, DateInput, TextInput from django.forms import CheckboxSelectMultiple, Select, DateInput, TextInput
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from phonenumber_field.widgets import PhoneNumberInternationalFallbackWidget
import logging import logging
from core.models import User, Page, RealGroup, SithFile from core.models import User, Page, RealGroup, SithFile
# Widgets # Widgets
class SelectSingle(Select): class SelectSingle(Select):
...@@ -67,6 +70,26 @@ class RegisteringForm(UserCreationForm): ...@@ -67,6 +70,26 @@ class RegisteringForm(UserCreationForm):
user.save() user.save()
return user return user
# Image utils
from io import BytesIO
from PIL import Image
def scale_dimension(width, height, long_edge):
if width > height:
ratio = long_edge * 1. / width
else:
ratio = long_edge * 1. / height
return int(width * ratio), int(height * ratio)
def resize_image(im, edge, format):
from django.core.files.base import ContentFile
(w, h) = im.size
(width, height) = scale_dimension(w, h, long_edge=edge)
content = BytesIO()
im.resize((width, height), Image.ANTIALIAS).save(fp=content, format=format, dpi=[72, 72])
return ContentFile(content.getvalue())
class UserProfileForm(forms.ModelForm): class UserProfileForm(forms.ModelForm):
""" """
Form handling the user profile, managing the files Form handling the user profile, managing the files
...@@ -76,13 +99,16 @@ class UserProfileForm(forms.ModelForm): ...@@ -76,13 +99,16 @@ class UserProfileForm(forms.ModelForm):
class Meta: class Meta:
model = User model = User
fields = ['first_name', 'last_name', 'nick_name', 'email', 'date_of_birth', 'profile_pict', 'avatar_pict', 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', 'scrub_pict', 'sex', 'second_email', 'address', 'parent_address', 'phone', 'parent_phone',
'promo', 'forum_signature'] 'tshirt_size', 'role', 'department', 'dpt_option', 'semester', 'quote', 'school', 'promo',
'forum_signature']
widgets = { widgets = {
'date_of_birth': SelectDate, 'date_of_birth': SelectDate,
'profile_pict': forms.ClearableFileInput, 'profile_pict': forms.ClearableFileInput,
'avatar_pict': forms.ClearableFileInput, 'avatar_pict': forms.ClearableFileInput,
'scrub_pict': forms.ClearableFileInput, 'scrub_pict': forms.ClearableFileInput,
'phone': PhoneNumberInternationalFallbackWidget,
'parent_phone': PhoneNumberInternationalFallbackWidget,
} }
labels = { labels = {
'profile_pict': _("Profile: you need to be visible on the picture, in order to be recognized (e.g. by the barmen)"), 'profile_pict': _("Profile: you need to be visible on the picture, in order to be recognized (e.g. by the barmen)"),
...@@ -111,13 +137,12 @@ class UserProfileForm(forms.ModelForm): ...@@ -111,13 +137,12 @@ class UserProfileForm(forms.ModelForm):
parent = SithFile.objects.filter(parent=None, name="profiles").first() parent = SithFile.objects.filter(parent=None, name="profiles").first()
for field,f in files: for field,f in files:
with transaction.atomic(): 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: try:
if not (f.content_type == "image/jpeg" or im = Image.open(BytesIO(f.read()))
f.content_type == "image/png" or new_file = SithFile(parent=parent, name=self.generate_name(field, f),
f.content_type == "image/gif"): file=resize_image(im, 400, f.content_type.split('/')[-1]),
raise ValidationError(_("Bad image format, only jpeg, png, and gif are accepted")) owner=self.instance, is_folder=False, mime_type=f.content_type, size=f._size)
new_file.file.name = new_file.name
old = SithFile.objects.filter(parent=parent, name=new_file.name).first() old = SithFile.objects.filter(parent=parent, name=new_file.name).first()
if old: if old:
old.delete() old.delete()
...@@ -129,6 +154,10 @@ class UserProfileForm(forms.ModelForm): ...@@ -129,6 +154,10 @@ class UserProfileForm(forms.ModelForm):
self._errors.pop(field, None) self._errors.pop(field, None)
self.add_error(field, _("Error uploading file %(file_name)s: %(msg)s") % self.add_error(field, _("Error uploading file %(file_name)s: %(msg)s") %
{'file_name': f, 'msg': str(e.message)}) {'file_name': f, 'msg': str(e.message)})
except IOError:
self._errors.pop(field, None)
self.add_error(field, _("Error uploading file %(file_name)s: %(msg)s") %
{'file_name': f, 'msg': _("Bad image format, only jpeg, png, and gif are accepted")})
self._post_clean() self._post_clean()
class UserPropForm(forms.ModelForm): class UserPropForm(forms.ModelForm):
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment