Rework admin package

This commit is contained in:
Patrick Jentsch 2020-10-23 10:17:14 +02:00
parent 23441dab2e
commit b840746fed
8 changed files with 132 additions and 111 deletions

View File

@ -8,10 +8,10 @@ from ..models import Role, User
from ..profile import tasks as profile_tasks from ..profile import tasks as profile_tasks
@admin.route('/') @admin.route('/users')
@login_required @login_required
@admin_required @admin_required
def index(): def users():
users = User.query.all() users = User.query.all()
users = [dict(username=u.username, users = [dict(username=u.username,
email=u.email, email=u.email,
@ -19,21 +19,18 @@ def index():
confirmed=u.confirmed, confirmed=u.confirmed,
id=u.id) id=u.id)
for u in users] for u in users]
return render_template('admin/index.html.j2', return render_template('admin/users.html.j2', title='Users', users=users)
title='Administration tools',
users=users)
@admin.route('/user/<int:user_id>') @admin.route('/users/<int:user_id>')
@login_required @login_required
@admin_required @admin_required
def user(user_id): def user(user_id):
user = User.query.get_or_404(user_id) user = User.query.get_or_404(user_id)
return render_template('admin/user.html.j2', title='Administration: User', return render_template('admin/user.html.j2', title='Edit user', user=user)
user=user)
@admin.route('/user/<int:user_id>/delete') @admin.route('/users/<int:user_id>/delete')
@login_required @login_required
@admin_required @admin_required
def delete_user(user_id): def delete_user(user_id):
@ -42,7 +39,7 @@ def delete_user(user_id):
return redirect(url_for('admin.index')) return redirect(url_for('admin.index'))
@admin.route('/user/<int:user_id>/edit', methods=['GET', 'POST']) @admin.route('/users/<int:user_id>/edit', methods=['GET', 'POST'])
@login_required @login_required
@admin_required @admin_required
def edit_user(user_id): def edit_user(user_id):
@ -63,4 +60,5 @@ def edit_user(user_id):
edit_user_form.role.data = user.role_id edit_user_form.role.data = user.role_id
return render_template('admin/edit_user.html.j2', return render_template('admin/edit_user.html.j2',
edit_user_form=edit_user_form, edit_user_form=edit_user_form,
title='Administration: Edit user', user=user) title='Edit user',
user=user)

View File

@ -131,11 +131,11 @@ RessourceList.dataMappers = {
confirmed: user.confirmed, confirmed: user.confirmed,
email: user.email, email: user.email,
id: user.id, id: user.id,
link: `user/${user.id}`, link: `users/${user.id}`,
role_id: user.role_id, role_id: user.role_id,
username: user.username, username: user.username,
username2: user.username, username2: user.username,
"delete-link": `/admin/user/${user.id}/delete`, "delete-link": `/admin/users/${user.id}/delete`,
"delete-modal": `delete-user-${user.id}-modal`, "delete-modal": `delete-user-${user.id}-modal`,
"delete-modal-trigger": `delete-user-${user.id}-modal`, "delete-modal-trigger": `delete-user-${user.id}-modal`,
}), }),

View File

@ -1,27 +1,35 @@
{% extends "nopaque.html.j2" %} {% extends "nopaque.html.j2" %}
{% import 'materialize/wtf.html.j2' as wtf %}
{% block page_content %} {% block page_content %}
<div class="col s12 m4"> <div class="container">
<h3 id="title">{{ user.username }}</h3> <div class="row">
<p id="description">Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren,</p> <div class="col s12">
<a class="waves-effect waves-light btn" href="{{ url_for('admin.user', user_id=user.id) }}"><i class="material-icons left">arrow_back</i>Back to user administration</a> <h1 id="title">Edit user</h1>
</div> </div>
<div class="col s12 m8"> <div class="col s12 m4">
<div class="card"> <h2>{{ user.username }}</h2>
<form method="POST"> <p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren,</p>
<div class="card-content"> <a class="waves-effect waves-light btn" href="{{ url_for('.user', user_id=user.id) }}"><i class="material-icons left">arrow_back</i>Back to user administration</a>
{{ edit_user_form.hidden_tag() }} </div>
{{ M.render_field(edit_user_form.username, data_length='64', material_icon='account_circle') }}
{{ M.render_field(edit_user_form.email, class_='validate', material_icon='email', type='email') }} <div class="col s12 m8">
{{ M.render_field(edit_user_form.role, material_icon='swap_vert') }} <div class="card">
{{ M.render_field(edit_user_form.confirmed, material_icon='check') }} <form method="POST">
<div class="card-content">
{{ edit_user_form.hidden_tag() }}
{{ wtf.render_field(edit_user_form.username, data_length='64', material_icon='account_circle') }}
{{ wtf.render_field(edit_user_form.email, class_='validate', material_icon='email', type='email') }}
{{ wtf.render_field(edit_user_form.role, material_icon='swap_vert') }}
{{ wtf.render_field(edit_user_form.confirmed, material_icon='check') }}
</div>
<div class="card-action right-align">
{{ wtf.render_field(edit_user_form.submit, material_icon='send') }}
</div>
</form>
</div> </div>
<div class="card-action right-align"> </div>
{{ M.render_field(edit_user_form.submit, material_icon='send') }}
</div>
</form>
</div> </div>
</div> </div>
{% endblock %} {% endblock %}

View File

@ -1,42 +0,0 @@
{% extends "nopaque.html.j2" %}
{% set full_width = True %}
{% block page_content %}
<div class="col s12">
<div class="card">
<div class="card-content" id="users">
<span class="card-title">User list</span>
<div class="input-field">
<i class="material-icons prefix">search</i>
<input id="search-user" class="search" type="search"></input>
<label for="search-user">Search user</label>
</div>
<ul class="pagination paginationTop"></ul>
<table class="highlight responsive-table">
<thead>
<tr>
<th class="sort" data-sort="username">Username</th>
<th class="sort" data-sort="email">Email</th>
<th class="sort" data-sort="role_id">Role</th>
<th class="sort" data-sort="confirmed">Confirmed Status</th>
<th class="sort" data-sort="id">Id</th>
<th>{# Actions #}</th>
</tr>
</thead>
<tbody class="list">
</tbody>
</table>
<ul class="pagination paginationBottom"></ul>
</div>
</div>
</div>
<script type="module">
import {RessourceList} from '../../static/js/nopaque.lists.js';
let userList = new RessourceList('users', null, "User", RessourceList.options.extended);
document.addEventListener("DOMContentLoaded", () => {
userList._add({{ users|tojson|safe }});
});
</script>
{% endblock %}

View File

@ -1,34 +1,40 @@
{% extends "nopaque.html.j2" %} {% extends "nopaque.html.j2" %}
{% block page_content %} {% block page_content %}
<div class="col s12 m4"> <div class="container">
<h3 id="title">{{ user.username }}</h3> <div class="row">
<p id="description">Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren,</p> <div class="col s12">
<a class="waves-effect waves-light btn" href="{{ url_for('admin.index') }}"><i class="material-icons left">arrow_back</i>Back to admin board</a> <h1>{{ title }}</h1>
</div> </div>
<div class="col s12 m8"> <div class="col s12 m4">
<div class="card"> <h2>{{ user.username }}</h2>
<div class="card-content"> <p id="description">Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren,</p>
<span class="card-title">User information</span> <a class="waves-effect waves-light btn" href="{{ url_for('.users') }}"><i class="material-icons left">arrow_back</i>Back to Users</a>
<ul>
<li>Username: {{ user.username }}</li>
<li>Email: {{ user.email }}</li>
<li>ID: {{ user.id }}</li>
<li>Member since: {{ user.member_since.strftime('%m/%d/%Y, %H:%M:%S %p') }}</li>
<li>Confirmed status: {{ user.confirmed }}</li>
<li>Last seen: {{ user.last_seen.strftime('%m/%d/%Y, %H:%M:%S %p') }}</li>
<li>Role ID: {{ user.role_id }}</li>
<li>Permissions as Int: {{ user.role.permissions }}</li>
<li>Role name: {{ user.role.name }}</li>
</ul>
</div> </div>
<div class="card-action right-align">
<a href="{{ url_for('admin.edit_user', user_id=user.id) }}" class="waves-effect waves-light btn"><i class="material-icons left">edit</i>Edit</a> <div class="col s12 m8">
<a data-target="delete-user-modal" class="waves-effect waves-light btn red modal-trigger"><i class="material-icons left">delete</i>Delete</a> <div class="card">
<div class="card-content">
<span class="card-title">User information</span>
<ul>
<li>Username: {{ user.username }}</li>
<li>Email: {{ user.email }}</li>
<li>ID: {{ user.id }}</li>
<li>Member since: {{ user.member_since.strftime('%m/%d/%Y, %H:%M:%S %p') }}</li>
<li>Confirmed status: {{ user.confirmed }}</li>
<li>Last seen: {{ user.last_seen.strftime('%m/%d/%Y, %H:%M:%S %p') }}</li>
<li>Role ID: {{ user.role_id }}</li>
<li>Permissions as Int: {{ user.role.permissions }}</li>
<li>Role name: {{ user.role.name }}</li>
</ul>
</div>
<div class="card-action right-align">
<a href="{{ url_for('.edit_user', user_id=user.id) }}" class="waves-effect waves-light btn"><i class="material-icons left">edit</i>Edit</a>
<a data-target="delete-user-modal" class="waves-effect waves-light btn red modal-trigger"><i class="material-icons left">delete</i>Delete</a>
</div>
</div>
</div> </div>
</div>
</div>
<div class="col s12 l6"> <div class="col s12 l6">
<h3>Corpora</h3> <h3>Corpora</h3>
@ -92,21 +98,23 @@
<!-- Modals --> <!-- Modals -->
<div id="delete-user-modal" class="modal"> <div id="delete-user-modal" class="modal">
<div class="modal-content"> <div class="modal-content">
<h4>Confirm user deletion</h4> <h3>Delete user</h3>
<p>Do you really want to delete the user {{ user.username }}? All associated data will be permanently deleted!</p> <p>Do you really want to delete the user {{ user.username }}? All associated data will be permanently deleted!</p>
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<a href="#!" class="modal-close waves-effect waves-light btn">Cancel</a> <a href="#!" class="modal-close waves-effect waves-light btn">Cancel</a>
<a href="{{ url_for('admin.delete_user', user_id=user.id) }}" class="modal-close waves-effect waves-light btn red"><i class="material-icons left">delete</i>Delete</a> <a href="{{ url_for('.delete_user', user_id=user.id) }}" class="modal-close waves-effect waves-light btn red"><i class="material-icons left">delete</i>Delete</a>
</div> </div>
</div> </div>
<script type="module">
import {RessourceList} from '../../static/js/nopaque.lists.js';
let corpusList = new RessourceList("corpora", nopaque.foreignCorporaSubscribers, "Corpus");
let jobList = new RessourceList("jobs", nopaque.foreignJobsSubscribers, "Job");
document.addEventListener("DOMContentLoaded", () => {
nopaque.socket.emit("foreign_user_data_stream_init", {{ user.id }});
});
</script>
{% endblock %} {% endblock %}
{% block scripts %}
{{ super() }}
<script type="module">
import {RessourceList} from '{{ url_for('static', filename='js/nopaque.lists.js') }}';
let corpusList = new RessourceList("corpora", nopaque.foreignCorporaSubscribers, "Corpus");
let jobList = new RessourceList("jobs", nopaque.foreignJobsSubscribers, "Job");
nopaque.socket.emit("foreign_user_data_stream_init", {{ user.id }});
</script>
{% endblock scripts %}

View File

@ -0,0 +1,48 @@
{% extends "nopaque.html.j2" %}
{% block page_content %}
<div class="container">
<div class="row">
<div class="col s12">
<h1>{{ title }}</h1>
</div>
<div class="col s12">
<div class="card">
<div class="card-content" id="users">
<div class="input-field">
<i class="material-icons prefix">search</i>
<input id="search-user" class="search" type="text"></input>
<label for="search-user">Search user</label>
</div>
<ul class="pagination paginationTop"></ul>
<table class="highlight responsive-table">
<thead>
<tr>
<th class="sort" data-sort="username">Username</th>
<th class="sort" data-sort="email">Email</th>
<th class="sort" data-sort="role_id">Role</th>
<th class="sort" data-sort="confirmed">Confirmed Status</th>
<th class="sort" data-sort="id">Id</th>
<th>{# Actions #}</th>
</tr>
</thead>
<tbody class="list">
</tbody>
</table>
<ul class="pagination paginationBottom"></ul>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block scripts %}
{{ super() }}
<script type="module">
import {RessourceList} from '{{ url_for('static', filename='js/nopaque.lists.js') }}';
let userList = new RessourceList('users', null, "User", RessourceList.options.extended);
userList._add({{ users|tojson}});
</script>
{% endblock scripts %}

View File

@ -6,6 +6,7 @@
<div class="col s12"> <div class="col s12">
<h1>{{ title }}</h1> <h1>{{ title }}</h1>
</div> </div>
<div class="col s12"> <div class="col s12">
<div class="card" id="beta-launch"> <div class="card" id="beta-launch">
<div class="card-content"> <div class="card-content">

View File

@ -136,7 +136,7 @@
{% if current_user.is_administrator() %} {% if current_user.is_administrator() %}
<li><div class="divider"></div></li> <li><div class="divider"></div></li>
<li><a class="subheader">Administration</a></li> <li><a class="subheader">Administration</a></li>
<li><a href="{{ url_for('admin.index') }}"><i class="material-icons">build</i>Administration tools</a></li> <li><a href="{{ url_for('admin.users') }}"><i class="material-icons">build</i>Administration tools</a></li>
{% endif %} {% endif %}
</ul> </ul>
{% endblock sidenav %} {% endblock sidenav %}