parent
b79bac1fc4
commit
b108ce4cfe
|
@ -110,6 +110,14 @@ class UpdateAccountForm(FlaskForm):
|
|||
Optional(),
|
||||
]
|
||||
)
|
||||
title = SelectField(
|
||||
'Titre',
|
||||
coerce=int,
|
||||
validators=[
|
||||
Optional(),
|
||||
vd.own_title,
|
||||
]
|
||||
)
|
||||
newsletter = BooleanField(
|
||||
'Inscription à la newsletter',
|
||||
description='Un mail par trimestre environ, pour être prévenu des concours, évènements et nouveautés.',
|
||||
|
@ -226,6 +234,14 @@ class AdminUpdateAccountForm(FlaskForm):
|
|||
Optional(),
|
||||
],
|
||||
)
|
||||
title = SelectField(
|
||||
'Titre',
|
||||
coerce=int,
|
||||
validators=[
|
||||
Optional(),
|
||||
# Admin can set any title to any member!
|
||||
]
|
||||
)
|
||||
newsletter = BooleanField(
|
||||
'Inscription à la newsletter',
|
||||
description='Un mail par trimestre environ, pour être prévenu des concours, évènements et nouveautés.',
|
||||
|
|
|
@ -7,7 +7,7 @@ from PIL import Image
|
|||
from app import app, db
|
||||
from app.models.privs import SpecialPrivilege, Group, GroupMember, \
|
||||
GroupPrivilege
|
||||
from app.models.trophies import Trophy, TrophyMember
|
||||
from app.models.trophies import Trophy, TrophyMember, Title
|
||||
from app.models.notification import Notification
|
||||
import app.utils.unicode_names as unicode_names
|
||||
from app.utils.notify import notify
|
||||
|
@ -105,6 +105,10 @@ class Member(User):
|
|||
signature = db.Column(db.UnicodeText)
|
||||
birthday = db.Column(db.Date)
|
||||
|
||||
# Displayed title, if set
|
||||
title_id = db.Column(db.Integer, db.ForeignKey('title.id'), nullable=True)
|
||||
title = db.relationship('Title', foreign_keys=title_id)
|
||||
|
||||
# Settings
|
||||
newsletter = db.Column(db.Boolean, default=False)
|
||||
|
||||
|
@ -204,6 +208,8 @@ class Member(User):
|
|||
self.newsletter = data["newsletter"]
|
||||
if "avatar" in data:
|
||||
self.set_avatar(data["avatar"])
|
||||
if "title" in data:
|
||||
self.title = Title.query.get(data["title"])
|
||||
|
||||
# For admins only
|
||||
if "email_confirmed" in data:
|
||||
|
|
|
@ -4,6 +4,7 @@ from app import app, db
|
|||
from app.forms.account import UpdateAccountForm, RegistrationForm, \
|
||||
DeleteAccountForm, AskResetPasswordForm, ResetPasswordForm
|
||||
from app.models.users import Member
|
||||
from app.models.trophies import Title
|
||||
from app.utils.render import render
|
||||
from app.utils.send_mail import send_validation_mail, send_reset_password_mail
|
||||
from app.utils.priv_required import guest_only
|
||||
|
@ -16,6 +17,9 @@ from config import V5Config
|
|||
@login_required
|
||||
def edit_account():
|
||||
form = UpdateAccountForm()
|
||||
titles = [(t.id, t.name) for t in current_user.trophies if isinstance(t, Title)]
|
||||
titles.insert(0, (-1, "Membre"))
|
||||
form.title.choices = titles
|
||||
if form.submit.data:
|
||||
if form.validate_on_submit():
|
||||
current_user.update(
|
||||
|
@ -25,6 +29,7 @@ def edit_account():
|
|||
birthday=form.birthday.data,
|
||||
signature=form.signature.data,
|
||||
bio=form.biography.data,
|
||||
title=form.title.data,
|
||||
newsletter=form.newsletter.data
|
||||
)
|
||||
db.session.merge(current_user)
|
||||
|
|
|
@ -3,7 +3,7 @@ from flask_login import current_user
|
|||
from wtforms import BooleanField
|
||||
from app.utils.priv_required import priv_required
|
||||
from app.models.users import Member
|
||||
from app.models.trophies import Trophy
|
||||
from app.models.trophies import Trophy, Title
|
||||
from app.models.privs import Group
|
||||
from app.forms.account import AdminUpdateAccountForm, AdminDeleteAccountForm, \
|
||||
AdminAccountEditTrophyForm, AdminAccountEditGroupForm
|
||||
|
@ -35,6 +35,10 @@ def adm_edit_account(user_id):
|
|||
setattr(GroupForm, "user_groups", [f'g{g.id}' for g in user.groups])
|
||||
group_form = GroupForm(prefix="group")
|
||||
|
||||
titles = [(t.id, t.name) for t in Title.query.all()]
|
||||
titles.insert(0, (-1, "Membre"))
|
||||
form.title.choices = titles
|
||||
|
||||
if form.submit.data:
|
||||
if form.validate_on_submit():
|
||||
newname = form.username.data
|
||||
|
@ -52,6 +56,7 @@ def adm_edit_account(user_id):
|
|||
password=form.password.data or None,
|
||||
birthday=form.birthday.data,
|
||||
signature=form.signature.data,
|
||||
title=form.title.data,
|
||||
bio=form.biography.data,
|
||||
newsletter=form.newsletter.data,
|
||||
xp=form.xp.data or None,
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
.form input[type='password'],
|
||||
.form input[type='search'],
|
||||
.form textarea,
|
||||
.form select,
|
||||
.trophies-panel > div {
|
||||
display: block;
|
||||
width: 100%; padding: 6px 8px;
|
||||
|
@ -49,6 +50,9 @@
|
|||
max-width: 100%;
|
||||
resize: vertical;
|
||||
}
|
||||
.form select {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.form progress.entropy {
|
||||
display: none; /* display with Js enabled */
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
.profile {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 265px;
|
||||
}
|
||||
.profile-avatar {
|
||||
width: 128px;
|
||||
|
|
|
@ -51,6 +51,13 @@
|
|||
</div>
|
||||
|
||||
<h2>À propos</h2>
|
||||
<div>
|
||||
{{ form.title.label }}
|
||||
{{ form.title }}
|
||||
{% for error in form.title.errors %}
|
||||
<span class="msgerror">{{ error }}</span>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<div>
|
||||
{{ form.birthday.label }}
|
||||
{{ form.birthday(value=current_user.birthday) }}
|
||||
|
|
|
@ -61,6 +61,13 @@
|
|||
</div>
|
||||
|
||||
<h2>À propos</h2>
|
||||
<div>
|
||||
{{ form.title.label }}
|
||||
{{ form.title }}
|
||||
{% for error in form.title.errors %}
|
||||
<span class="msgerror">{{ error }}</span>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<div>
|
||||
{{ form.birthday.label }}
|
||||
{{ form.birthday(value=user.birthday) }}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<img class="profile-avatar" src="{{ url_for('avatar', filename=user.avatar) }}" alt="Avatar de {{ user.name }}">
|
||||
<div>
|
||||
<div class="profile-name"><a href="{{ url_for('user', username=user.name) }}">{{ user.name }}</a></div>
|
||||
<div class="profile-title">Membre</div>
|
||||
<div class="profile-title">{{ user.title.name if user.title else "Membre" }}</div>
|
||||
<div class="profile-points">Niveau {{ user.level[0] }} <span>({{ user.xp }})</span></div>
|
||||
<div class="profile-points-small">N{{ user.level[0] }} <span>({{ user.xp }})</span></div>
|
||||
<div class="profile-xp"><div style='width: {{ user.level[1] }}%;'></div></div>
|
||||
|
|
|
@ -2,9 +2,11 @@ from flask_login import current_user
|
|||
from wtforms.validators import ValidationError
|
||||
from PIL import Image
|
||||
from app.models.users import Member, User
|
||||
from app.models.trophies import Title
|
||||
from app.utils.valid_name import valid_name
|
||||
from app.utils.unicode_names import normalize
|
||||
from math import log
|
||||
from werkzeug.exceptions import NotFound
|
||||
import app.utils.ldap as ldap
|
||||
from config import V5Config
|
||||
|
||||
|
@ -117,3 +119,20 @@ def id_exists(object):
|
|||
def css(form, css):
|
||||
"""Check if input is valid and sane CSS"""
|
||||
pass
|
||||
|
||||
def own_title(form, title):
|
||||
# Everyone can use "Member"
|
||||
if title.data == -1:
|
||||
return True
|
||||
|
||||
try:
|
||||
t = Title.query.get_or_404(title.data)
|
||||
except NotFound:
|
||||
return False
|
||||
except ValueError:
|
||||
return False
|
||||
|
||||
if t in current_user.trophies:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
"""Add displayed title to Member
|
||||
|
||||
Revision ID: 001d2eaf0413
|
||||
Revises: acf72cf31eea
|
||||
Create Date: 2020-07-29 00:13:27.775769
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '001d2eaf0413'
|
||||
down_revision = 'acf72cf31eea'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.add_column('member', sa.Column('title_id', sa.Integer(), nullable=True))
|
||||
op.create_foreign_key(None, 'member', 'title', ['title_id'], ['id'])
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.drop_constraint(None, 'member', type_='foreignkey')
|
||||
op.drop_column('member', 'title_id')
|
||||
# ### end Alembic commands ###
|
Loading…
Reference in New Issue