Merge branch 'dev' into preprod

This commit is contained in:
Darks 2020-07-23 19:21:57 +02:00
commit dbf44746d9
Signed by: Darks
GPG Key ID: F61F10FA138E797C
14 changed files with 85 additions and 29 deletions

1
.gitignore vendored
View File

@ -2,6 +2,7 @@
__pycache__/
app/__pycache__/
app/static/avatars/
app/static/images/trophies/
## Devlopement files

View File

@ -5,6 +5,7 @@ from flask_login import LoginManager
from flask_mail import Mail
from config import Config
import time
import slugify
app = Flask(__name__)
app.config.from_object(Config)
@ -49,3 +50,8 @@ from app.routes.forum import index, topic
from app.utils import pluralize # To use pluralize into the templates
from app.utils import date
from app.utils import is_title
# Add slugify into the available functions in every template
app.jinja_env.globals.update(
slugify=slugify.slugify
)

BIN
app/data/trophies.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

View File

@ -2,6 +2,7 @@
# name Trophy name as displayed on the site.
# is_title If True, the trophy can be worn as a title next to the avatar.
# description Detailed description to be shown on profile page.
# hidden Not shown unless awarded (for unique titles).
# Manually awarded
-
@ -185,3 +186,8 @@
is_title: True
description: Foudroyer les cœurs à 5 reprises!
hidden: False
-
name: Survivant de la v42
is_title: False
description: A connu la v42 de Planète Casio.
hidden: True

View File

@ -189,8 +189,8 @@ class AdminUpdateAccountForm(FlaskForm):
vd.email,
],
)
email_validate = BooleanField(
"Envoyer un email de validation à la nouvelle adresse",
email_confirmed = BooleanField(
"Confirmer l'email",
description="Si décoché, l'utilisateur devra demander explicitement un email "\
"de validation, ou faire valider son adresse email par un administrateur.",
)

View File

@ -160,14 +160,15 @@ class Member(User):
"""
Update all or part of the user's metadata. The [data] dictionary
accepts the following keys:
"email" str User mail ddress
"password" str Raw password
"bio" str Biograpy
"signature" str Post signature
"birthday" date Birthday date
"newsletter" bool Newsletter setting
"xp" int Experience points
"avatar" File Avatar image
"email" str User mail address
"email_confirmed" bool User mail address confirmed
"password" str Raw password
"bio" str Biograpy
"signature" str Post signature
"birthday" date Birthday date
"newsletter" bool Newsletter setting
"xp" int Experience points
"avatar" File Avatar image
For future compatibility, other attributes are silently ignored. None
values can be specified and are ignored.
@ -198,6 +199,8 @@ class Member(User):
self.set_avatar(data["avatar"])
# For admins only
if "email_confirmed" in data:
self.email_confirmed = data["email_confirmed"]
if "xp" in data:
self.xp = data["xp"]

View File

@ -48,6 +48,7 @@ def adm_edit_account(user_id):
avatar=form.avatar.data or None,
name=form.username.data or None,
email=form.email.data or None,
email_confirmed=form.email_confirmed.data,
password=form.password.data or None,
birthday=form.birthday.data,
signature=form.signature.data,

View File

@ -1,15 +1,18 @@
table {
border-collapse: collapse;
border-color: #d8d8d8;
border-collapse: collapse;
border-color: var(--border);
border-style: solid;
border-width: 0 0 1px 0;
}
table tr:nth-child(even) {
background: rgba(0, 0, 0, .05);
background: var(--background);
}
table tr:nth-child(even) {
background: var(--background);
}
table th {
background: #e0e0e0;
border-color: #d0d0d0;
background: var(--background);
border-color: var(--border);
border-style: solid;
border-width: 1px 0;
padding: 2px 6px;

View File

@ -25,6 +25,17 @@
--hr-border: 1px solid #b0b0b0;
}
table {
--border: #d8d8d8;
}
table tr:nth-child(even) {
--background: rgba(0, 0, 0, .05);
}
table th {
--background: #e0e0e0;
--border: #d0d0d0;
}
.form {
--background: #ffffff;
--text: #000000;

View File

@ -61,7 +61,7 @@
border-radius: 2px;
}
.trophy img {
height: 50px; margin-right: 5px;
height: 48px; margin-right: 8px;
}
.trophy div > * {
display: block;

View File

@ -46,7 +46,7 @@
<div class="trophies">
{% for t in trophies if t in member.trophies or t.hidden == False %}
<div class="trophy {{ '' if t in member.trophies else 'disabled' }}">
<img src="{{ url_for('static', filename='images/fa_124.png') }}">
<img src="{{ url_for('static', filename='images/trophies/'+slugify(t.name))+'.png' }}">
<div>
<em>{{ t.name }}</em>
<span>{{ t.description }}</span>

View File

@ -37,9 +37,9 @@
{% endfor %}
</div>
<div>
{{ form.email_validate.label }}
{{ form.email_validate(checked=True) }}
<div class=desc>{{ form.email_validate.description }}</div>
{{ form.email_confirmed.label }}
{{ form.email_confirmed(checked=user.email_confirmed) }}
<div class=desc>{{ form.email_confirmed.description }}</div>
</div>
<div>
{{ form.password.label }}

View File

@ -13,19 +13,19 @@
<table style="width:90%; margin: auto;">
<tr><th>Pseudo</th><th>Email</th><th>Groupes</th>
<th>Privilèges spéciaux</th><th>Modifier</th></tr>
<th>Privilèges spéciaux</th><th>Modifier</th></tr>
{% for user in users %}
<tr><td><a href="{{ url_for('user_by_id', user_id=user.id) }}" title="Page de profil publique de {{ user.name }}">{{ user.name }}</a></td>
<td>{{ user.email }}</td>
<td style="color: {{ 'red' if not user.email_confirmed else 'inherit' }};">{{ user.email }}</td>
<td>{% for g in user.groups %}
<span style="{{ g.css }}">{{ g.name }}</span>
{{ ', ' if not loop.last }}
{% endfor %}</td>
<span style="{{ g.css }}">{{ g.name }}</span>
{{ ', ' if not loop.last }}
{% endfor %}</td>
<td>{% for priv in user.special_privileges() %}
<code>{{ priv }}</code>
{{- ', ' if not loop.last }}
{% endfor %}</td>
<code>{{ priv }}</code>
{{- ', ' if not loop.last }}
{% endfor %}</td>
<td style="text-align: center"><a href="{{ url_for('adm_edit_account', user_id=user.id) }}">Modifier</a></td>
</tr>
{% endfor %}

View File

@ -10,6 +10,8 @@ import os
import sys
import yaml
import readline
import slugify
from PIL import Image
help_msg = """
This is the Planète Casio master shell. Type 'exit' or C-D to leave.
@ -37,7 +39,7 @@ the database.
Type 'add-group <member> #<group-id>' to add a new member to a group.
Type 'create-trophies' to reset trophies and titles.
Type 'create-trophies' to reset trophies and titles and their icons.
Type 'create-forums' to reset the forum tree.
"""
@ -183,6 +185,29 @@ def create_trophies():
print(f"Created {len(tr)} trophies.")
# Create their icons in /app/static/images/trophies
names = [ slugify.slugify(t["name"]) for t in tr ]
src = os.path.join(app.root_path, "data", "trophies.png")
dst = os.path.join(app.root_path, "static", "images", "trophies")
try:
os.mkdir(dst)
except FileExistsError:
pass
img = Image.open(src)
def trophy_iterator(img):
for y in range(img.height // 26):
for x in range(img.width // 26):
icon = img.crop((26*x+1, 26*y+1, 26*x+25, 26*y+25))
# Skip blank squares in the source image
if len(icon.getcolors()) > 1:
yield icon.resize((48,48))
for (name, icon) in zip(names, trophy_iterator(img)):
icon.save(os.path.join(dst, f"{name}.png"))
def create_forums():
# Clean up forums
forums("clear")