Add new admin blueprint with new user delete feature. Reorganize templates etc.

This commit is contained in:
Stephan Porada 2019-08-15 15:56:53 +02:00
parent 93330c0efb
commit bccf661957
8 changed files with 134 additions and 15 deletions

View File

@ -33,6 +33,9 @@ def create_app(config_name):
from .main import main as main_blueprint from .main import main as main_blueprint
app.register_blueprint(main_blueprint) app.register_blueprint(main_blueprint)
from .admin import admin as admin_blueprint
app.register_blueprint(admin_blueprint, url_prefix='/admin')
return app return app

5
app/admin/__init__.py Normal file
View File

@ -0,0 +1,5 @@
from flask import Blueprint
admin = Blueprint('admin', __name__)
from . import views

43
app/admin/views.py Normal file
View File

@ -0,0 +1,43 @@
from flask import (abort, current_app, flash, redirect, request,
render_template, url_for, send_from_directory)
from flask_login import current_user, login_required
from ..models import Corpus, User
from ..tables import AdminUserTable, AdminUserItem
from . import admin
from ..decorators import admin_required
from .. import db
import os
@admin.route('/overview', methods=['GET', 'POST'])
@login_required
@admin_required
def for_admins_only():
users = User.query.order_by(User.username).all()
items = [AdminUserItem(u.username, u.email, u.role_id, u.confirmed, u.id) for u in users]
table = AdminUserTable(items).__html__() # converts table object to html string
table = table.replace('tbody', 'tbody class="list"', 1) # add class list to tbody element. Needed by list.js
return render_template('admin/admin.html.j2', title='Administration tools',
table=table)
@admin.route('/overview/admin_user_page/<int:user_id>', methods=['GET', 'POST'])
@login_required
@admin_required
def admin_user_page(user_id):
selected_user = User.query.filter_by(id=user_id).first()
title = 'Administration of user {} with ID: {}'.format(selected_user.username,
selected_user.id)
return render_template('admin/admin_user_page.html.j2',
title=title, selected_user=selected_user)
@admin.route('/overview/admin_user_page/delete/<int:user_id>', methods=['GET', 'POST'])
@login_required
@admin_required
def admin_delete_user(user_id):
selected_user = User.query.filter_by(id=user_id).first()
db.session.delete(selected_user)
db.session.commit()
flash('User {} has been deleted!'.format(user_id))
return redirect(url_for('admin.for_admins_only'))

View File

@ -15,18 +15,6 @@ def index():
return render_template('main/index.html.j2', title='Opaque') return render_template('main/index.html.j2', title='Opaque')
@main.route('/admin', methods=['GET', 'POST'])
@login_required
@admin_required
def for_admins_only():
users = User.query.order_by(User.username).all()
items = [AdminUserItem(u.username, u.email, u.role_id, u.confirmed) for u in users]
table = AdminUserTable(items).__html__() # converts table object to html string
table = table.replace('tbody', 'tbody class="list"', 1) # add class list to tbody element. Needed by list.js
return render_template('main/admin.html.j2', title='Administration tools',
table=table)
@main.route('/corpora/<int:corpus_id>') @main.route('/corpora/<int:corpus_id>')
@login_required @login_required
def corpus(corpus_id): def corpus(corpus_id):

View File

@ -1,4 +1,4 @@
from flask_table import Table, Col from flask_table import Table, Col, ButtonCol, LinkCol
class AdminUserTable(Table): class AdminUserTable(Table):
@ -10,6 +10,10 @@ class AdminUserTable(Table):
email = Col('Email', column_html_attrs={'class': 'email'}) email = Col('Email', column_html_attrs={'class': 'email'})
role_id = Col('Role', column_html_attrs={'class': 'role'}) role_id = Col('Role', column_html_attrs={'class': 'role'})
confirmed = Col('Confrimed Status', column_html_attrs={'class': 'confirmed'}) confirmed = Col('Confrimed Status', column_html_attrs={'class': 'confirmed'})
id = Col('User Id', column_html_attrs={'class': 'id'})
url = LinkCol('Profile', 'admin.admin_user_page',
url_kwargs=dict(user_id='id'),
anchor_attrs={'class': 'waves-effect waves-light btn-small'})
class AdminUserItem(object): class AdminUserItem(object):
@ -17,11 +21,12 @@ class AdminUserItem(object):
Describes one item like one row per table. Describes one item like one row per table.
""" """
def __init__(self, username, email, role_id, confirmed): def __init__(self, username, email, role_id, confirmed, id):
self.username = username self.username = username
self.email = email self.email = email
self.role_id = role_id self.role_id = role_id
self.confirmed = confirmed self.confirmed = confirmed
self.id = id
if self.role_id == 1: if self.role_id == 1:
self.role_id = 'User' self.role_id = 'User'

View File

@ -0,0 +1,75 @@
{% extends "base.html.j2" %}
{% block page_content %}
<div class="col s12 m6">
<div class="card large">
<div class="card-content">
<span class="card-title">User information</span>
</div>
</div>
</div>
<div class="col s12 m6">
<div class="card large">
<div class="card-content">
<span class="card-title">User Jobs</span>
<div id="users">
<div class="input-field">
<i class="material-icons prefix">search</i>
<input id="search-corpus" class="search" type="text"></input>
<label for="search-corpus">Search users</label>
</div>
<div class="collection list">
{% for job in selected_user.jobs.all() %}
{% if job.service == 'nlp' %}
{% set service_color = 'blue' %}
{% set service_icon = 'format_textdirection_l_to_r' %}
{% elif job.service =='ocr' %}
{% set service_color = 'green' %}
{% set service_icon = 'find_in_page' %}
{% else %}
{% set service_color = 'red' %}
{% set service_icon = 'help' %}
{% endif %}
{% if job.status == 'pending' %}
{% set badge_color = 'amber' %}
{% elif job.status =='running' %}
{% set badge_color = 'indigo' %}
{% elif job.status =='complete' %}
{% set badge_color = 'teal' %}
{% else %}
{% set badge_color = 'red' %}
{% endif %}
<a href="{{ url_for('main.job', job_id=job.id) }}" class="collection-item avatar">
<i class="material-icons circle {{ service_color }}">{{ service_icon }}</i>
<span class="new badge {{ badge_color }}" data-badge-caption="">{{ job.status }}</span>
<span class="title">{{ job.title }}</span>
<p>{{ job.description }}</p>
</a>
{% endfor %}
</div>
<ul class="pagination"></ul>
</div>
</div>
</div>
</div>
<div class="col s12">
<div class="card large">
<div class="card-content">
<span class="card-title">Administration actions</span>
<!-- Confirm deletion of selected user with modal dialogue
Modal Trigger-->
<a href="#modal-confirm-delete" class="waves-effect waves-light btn modal-trigger"><i class="material-icons left">delete</i>Delete User</a>
<!-- Modal Strucutre -->
<div id="modal-confirm-delete" class="modal">
<div class="modal-content">
<h4>Confirm deletion</h4>
<p>Do you really want to delete the current selected user ({{selected_user.username}})?</p>
</div>
<div class="modal-footer">
<a href="{{url_for('admin.admin_delete_user', user_id=selected_user.id)}}" class="modal-close waves-effect waves-green btn red"><i class="material-icons left">delete</i>Delete User</a></a>
</div>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@ -95,7 +95,7 @@
{% if current_user.is_administrator() %} <!-- Shows only for admins --> {% if current_user.is_administrator() %} <!-- Shows only for admins -->
<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('main.for_admins_only') }}"><i class="material-icons">build</i>Administration tools</a></li> <li><a href="{{ url_for('admin.for_admins_only') }}"><i class="material-icons">build</i>Administration tools</a></li>
{% endif %} {% endif %}
</ul> </ul>
</header> </header>