Browse Source

admin: more on user and group generation

Also more titles and details on other pages of
the administration section.
master
lephe 8 months ago
parent
commit
9fe1104b45

+ 2
- 1
app/models/privs.py View File

@@ -44,9 +44,10 @@ class Group(db.Model):
members = db.relationship('Member', secondary=lambda:GroupMember,
back_populates='groups')

def __init__(self, name, css):
def __init__(self, name, css, descr):
self.name = name
self.css = css
self.description = descr
self.members = []

def __repr__(self):

+ 48
- 14
app/routes/admin.py View File

@@ -13,7 +13,7 @@ from app import app, db
@priv_required('admin-panel')
def admin():
class AdminForm(FlaskForm):
submit = SubmitField('Régénérer groupes, privilèges, membres de test')
submit = SubmitField('Régénérer les groupes, privilèges, et comptes communs')

form = AdminForm()
if form.validate_on_submit():
@@ -23,31 +23,57 @@ def admin():
db.session.commit( )

# Create base groups
g_admins = Group('Administrateur', 'color: red')
g_modos = Group('Modérateur', 'color: green')
g_redacs = Group('Rédacteur', 'color: blue')
g_community = Group('Compte communautaire', 'background: #d8d8d8;' +
'border-radius: 4px; color: #303030; padding: 1px 2px')
db.session.add(g_admins)
db.session.add(g_modos)
db.session.add(g_redacs)
db.session.add(g_community)
groups = [
('Administrateur', 'color: #ee0000',
"Vous voyez Chuck Norris ? Pareil."),
('Modérateur', 'color: green',
"Maîtres du kick, ils sont là pour faire respecter un semblant " +
"d'ordre."),
('Développeur', 'color: #4169e1',
"Les développeurs maintiennent et améliorent le code du site."),
('Rédacteur', 'color: blue',
"Rédigent les meilleurs articles de la page d'accueil, rien " +
"que pour vous <3"),
('Responsable communauté', 'color: DarkOrange',
"Anime les pages Twitter et Facebook de Planète Casio et " +
"surveille l'évolution du monde autour de nous !"),
('Partenaire', 'color: purple',
"Membres de l'équipe d'administration des sites partenaires."),
('Compte communautaire', 'background: #d8d8d8; border-radius: ' +
'4px; color:#303030; padding: 1px 2px',
"Compte à usage général de l'équipe de Planète Casio."),
('Robot', 'color: #cf25d0',
"♫ Je suis Nono, le petit robot, l'ami d'Ulysse ♫"),
('Membre de CreativeCalc', 'color: #222222',
"CreativeCalc est l'association qui gère Planète Casio."),
]
for g in groups:
db.session.add(Group(*g))

# Clean up test members
for name in "PlanèteCasio GLaDOS".split():
m = Member.query.filter_by(name=name).first()
if m is not None:
# TODO: Do a real member deletion, not just a hack like this
for sp in SpecialPrivilege.query.filter_by(mid=m.id):
db.session.delete(sp)
db.session.commit()
db.session.delete(m)
db.session.commit()
db.session.commit()

# Create template members

def addgroup(member, group):
g = Group.query.filter_by(name=group).first()
if g is not None:
member.groups.append(g)

m = Member('PlanèteCasio','contact@planet-casio.com','v5-forever')
m.groups.append(g_community)
addgroup(m, "Compte communautaire")
db.session.add(m)

m = Member('GLaDOS', 'glados@aperture.science', 'v5-forever')
m.groups.append(g_modos)
m.groups.append(g_redacs)
addgroup(m, "Robot")
db.session.add(m)
db.session.add(SpecialPrivilege(m, "edit-posts"))
db.session.add(SpecialPrivilege(m, "shoutbox-ban"))
@@ -94,6 +120,14 @@ def adm_delete_account(user_id):
user = Member.query.filter_by(id=user_id).first()
if not user:
abort(404)

# Note: A user deleting their own account will be disconnected.

# TODO: Add an overview of what will be deleted.
# * How many posts will be turned into guest posts
# * Option: purely delete the posts in question
# * How many PMs will be deleted (can't unassign PMs)
# * etc.
del_form = AdminDeleteAccountForm()
if request.method == "POST":
if del_form.validate_on_submit():

+ 19
- 6
app/static/css/global.css View File

@@ -41,11 +41,20 @@ a {
text-decoration: none;
color: #c61a1a;
}
a:hover {
text-decoration: underline;
}
a:focus {
outline: none;
}

/*
Lists
*/

ul {
line-height: 24px;
}

/*
Inputs
@@ -75,6 +84,10 @@ input[type="submit"] {
padding: 6px 10px; border-radius: 2px;
cursor: pointer;
font-family: 'DejaVu Sans', sans-serif; font-weight: 400;
cursor: pointer;
}
.button:hover {
text-decoration: none;
}

/* Checkbox */
@@ -94,24 +107,24 @@ input[type="checkbox"] {

.bg-green,
.bg-green {
background-color: #149641;
background: #149641;
color: #ffffff;
}
.bg-green:hover,
.bg-green:focus,
.bg-green:active {
background-color: #0f7331;
background: #0f7331;
}

.bg-red,
.bg-red {
background-color: #c0341d;
background: #d23a2f;
color: #ffffff;
}
.bg-red:hover,
.bg-red:focus,
.bg-red:active {
background-color: #aa3421;
background: #b32a20;
}

.bg-orange {
@@ -127,12 +140,12 @@ input[type="checkbox"] {
.bg-white,
.bg-white {
border: 1px solid #e5e5e5;
background-color: #ffffff;
background: #ffffff;
color: #000000;
}
.bg-white:hover,
.bg-white:focus,
.bg-white:active {
background-color: #f0f0f0;
background: #f0f0f0;
border-color: #e3e3e3;
}

+ 8
- 13
app/static/css/header.css View File

@@ -18,6 +18,9 @@ header .spacer {
flex: auto 1 0;
}

header .links {
margin-left: 16px;
}
header svg {
width: 24px; height: 24px; vertical-align: middle;
transition: .15s ease;
@@ -31,9 +34,11 @@ header a {
}

header form {
/* -24px for the search icon, -2px for the spacing between the search icon
and the field, +16px for spacing with the links */
margin-right: -10px;
/* The search icon is draws inside the input field but its space is allocated
on the right. Apply a negative margin to compensate this:
-24px for the search icon
-2px for the spacing between the search icon and the field */
margin-right: -26px;
}
header input[type="search"] {
display: inline-block; width: 250px;
@@ -58,13 +63,3 @@ header input[type="search"]:focus ~ a > svg > path {
#spotlight {
margin-left: 16px;
}
#spotlight a {
background: #d23a2f; padding: 8px 18px 6px 18px;
color: white;
height: 24px; line-height: 24px; padding: 6px 12px;
border-radius: 2px; border: 1px solid rgba(0, 0, 255, .1);
}
#spotlight a:hover {
background: #b32a20;
border-color: rgba(128, 128, 255, .05);
}

+ 4
- 1
app/static/css/table.css View File

@@ -4,6 +4,9 @@ table {
border-style: solid;
border-width: 0 0 1px 0;
}
table tr:nth-child(even) {
background: rgba(0, 0, 0, .05);
}
table th {
background: #e0e0e0;
border-color: #d0d0d0;
@@ -12,5 +15,5 @@ table th {
padding: 2px;
}
table td {
padding: 4px;
padding: 4px 6px;
}

+ 8
- 4
app/templates/admin/delete_account.html View File

@@ -1,16 +1,20 @@
{% extends "base/base.html" %}

{% block title %}
Panneau d'administration » <h1>Suppression du compte '{{ user.name }}'</h1>
{% endblock %}

{% block content %}
<section class="form">
<h1>Suppression du compte</h2>
<form action="{{ url_for('adm_delete_account', user_id=user.id) }}" method="post">
<h2>Suppression du compte de '{{ user.name }}'</h2>
<form action="{{ url_for('adm_delete_account', user_id=user.id) }}" method=post>
{{ del_form.hidden_tag() }}
<div>
{{ del_form.delete.label }}
{{ del_form.delete(checked=False) }}
<div style="font-size:80%;color:rgba(0,0,0,.5)">{{ del_form.delete.description }}</div>
<div style="font-size: 80%; color: gray">{{ del_form.delete.description }}</div>
{% for error in del_form.delete.errors %}
<span class="msgerror">{{ error }}</span>
<span class=msgerror>{{ error }}</span>
{% endfor %}
</div>
<div>{{ del_form.submit(class_="bg-red") }}</div>

+ 4
- 2
app/templates/admin/edit_account.html View File

@@ -1,13 +1,15 @@
{% extends "base/base.html" %}

{% block title %}
Panneau d'administration » <h1>Édition du compte de '{{ user.name }}'</h1>
{% endblock %}

{% block content %}
<section class="form">
<a href="{{ url_for('admin') }}" class="button bg-white">Retour à l'administration</a>
</section>

<section class="form">
<h1>Gestion du compte</h1>

<form action="{{ url_for('adm_edit_account', user_id=user.id) }}" method="post" enctype="multipart/form-data">
{{ form.hidden_tag() }}


+ 59
- 41
app/templates/admin/index.html View File

@@ -6,46 +6,64 @@ Panneau d'administration » <h1>Utilisateurs et groupes</h1>

{% block content %}
<section>
<h2>Listes des membres utiles</h2>

<table style="width:90%; margin: auto;">
<tr><th>Pseudo</th><th>Email</th><th>Date d'inscription</th><th>XP</th>
<th>Innovation</th><th>Newsletter</th><th>Modifier</th></tr>

{% for user in users %}
<tr><td><a href="{{ url_for('user_by_id', user_id=user.id) }}" >{{ user.name }}</a></td>
<td>{{ user.email }}</td>
<td>{{ user.register_date }}</td><td>{{ user.xp }}</td>
<td>{{ user.innovation }}</td>
<td>{{ "Oui" if user.newsletter else "Non" }}</td>
<td><a href="{{ url_for('adm_edit_account', user_id=user.id) }}" class="button">Modifier</a></td>
</tr>
{% endfor %}
</table>

<h2>Groupes et privilèges</h2>

<table style="width:90%; margin: auto;">
<tr><th>Groupe</th><th>Membres</th><th>Privilèges</th></tr>

{% for group in groups %}
<tr><td><span style="{{ group.css }}">{{ group.name }}</span></td><td>
{% for user in group.members %}
{{ user.name }}
{% endfor %}
</td><td>
{% for priv in group.privs %}
<code>{{ priv }}</code>
{% endfor %}
</td></tr>
{% endfor %}
</table>

<h2>Maintenance et développement</h2>

<form action='' method='POST'>
{{ form.hidden_tag() }}
{{ form.submit(class="bg-orange") }}
</form>
<p>Cette page présente une vue d'ensemble des utilisateurs et groupes, ainsi
que les privilèges associés. Seuls les utilisateurs appartenant à un
groupe ou possédant au moins un privilège spécial sont affichés.</p>

<h2>Membres associés à des groupes ou privilèges spéciaux</h2>

<table style="width:90%; margin: auto;">
<tr><th>Pseudo</th><th>Email</th><th>Date d'inscription</th><th>XP</th>
<th>Innovation</th><th>Newsletter</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>{{ user.register_date }}</td><td>{{ user.xp }}</td>
<td>{{ user.innovation }}</td>
<td>{{ "Oui" if user.newsletter else "Non" }}</td>
<td><a href="{{ url_for('adm_edit_account', user_id=user.id) }}">Modifier</a></td>
</tr>
{% endfor %}
</table>

<h2>Liste des groupes</h2>

<table style="width:90%; margin: auto;">
<tr><th>Groupe</th><th>Membres</th><th>Privilèges</th></tr>

{% for group in groups %}
<tr><td><span style="{{ group.css }}">{{ group.name }}</span></td><td>
{% for user in group.members %}
{{ user.name }}
{% endfor %}
</td><td>
{% for priv in group.privs %}
<code>{{ priv }}</code>
{% endfor %}
</td></tr>
{% endfor %}
</table>

<h2>Restauration des groupes et privilèges</h2>

<p>Cette fonction régénère un ensemble minimal de groupes et membres
permettant de lancer le forum. Elle opère les modifications
suivantes :</p>

<ul>
<li>Suppression de tous les groupes.</li>
<li>Création des groupes Administrateur, Modérateur, Développeur,
Rédacteur, Responsable communauté, Partenaire, Compte communautaire,
Robot, Membre de CreativeCalc.</li>
<li>Attribution des privilèges associés à ces groupes.</li>
<li>Recréation des comptes communs : PlanèteCasio (compte communautaire),
GLaDOS (robot).</li>
</ul>

<form action='' method='POST'>
{{ form.hidden_tag() }}
{{ form.submit(class="bg-orange") }}
</form>
</section>
{% endblock %}

+ 8
- 7
app/templates/base/header.html View File

@@ -9,14 +9,15 @@
</form>

{% if current_user.is_authenticated %}
<a href="{{ url_for('user', username=current_user.name) }}" role=button title='Mon compte'>
<svg viewBox="0 0 24 24">
<path d="M12,19.2C9.5,19.2 7.29,17.92 6,16C6.03,14 10,12.9 12,12.9C14,12.9 17.97,14 18,16C16.71,17.92 14.5,19.2 12,19.2M12,5A3,3 0 0,1 15,8A3,3 0 0,1 12,11A3,3 0 0,1 9,8A3,3 0 0,1 12,5M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12C22,6.47 17.5,2 12,2Z"></path>
</svg>
</a>
<div class=links>
<a href="{{ url_for('user', username=current_user.name) }}" role=button title='Mon compte'>
<svg viewBox="0 0 24 24">
<path d="M12,19.2C9.5,19.2 7.29,17.92 6,16C6.03,14 10,12.9 12,12.9C14,12.9 17.97,14 18,16C16.71,17.92 14.5,19.2 12,19.2M12,5A3,3 0 0,1 15,8A3,3 0 0,1 12,11A3,3 0 0,1 9,8A3,3 0 0,1 12,5M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12C22,6.47 17.5,2 12,2Z"></path>
</svg>
</a>
</div>
{% endif %}

<div id="spotlight">
<a href="#">Concours</a>
<a href="#">Jeu du mois : février 2019</a>
<a href="#" class="button bg-red">Jeu du mois : février 2019</a>
</div>

Loading…
Cancel
Save