mirror of
				https://gitlab.ub.uni-bielefeld.de/sfb1288inf/nopaque.git
				synced 2025-11-03 20:02:47 +00:00 
			
		
		
		
	Add new admin blueprint with new user delete feature. Reorganize templates etc.
This commit is contained in:
		@@ -33,6 +33,9 @@ def create_app(config_name):
 | 
			
		||||
    from .main import main as main_blueprint
 | 
			
		||||
    app.register_blueprint(main_blueprint)
 | 
			
		||||
 | 
			
		||||
    from .admin import admin as admin_blueprint
 | 
			
		||||
    app.register_blueprint(admin_blueprint, url_prefix='/admin')
 | 
			
		||||
 | 
			
		||||
    return app
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										5
									
								
								app/admin/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								app/admin/__init__.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
			
		||||
from flask import Blueprint
 | 
			
		||||
 | 
			
		||||
admin = Blueprint('admin', __name__)
 | 
			
		||||
 | 
			
		||||
from . import views
 | 
			
		||||
							
								
								
									
										43
									
								
								app/admin/views.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								app/admin/views.py
									
									
									
									
									
										Normal 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'))
 | 
			
		||||
@@ -15,18 +15,6 @@ def index():
 | 
			
		||||
    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>')
 | 
			
		||||
@login_required
 | 
			
		||||
def corpus(corpus_id):
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
from flask_table import Table, Col
 | 
			
		||||
from flask_table import Table, Col, ButtonCol, LinkCol
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AdminUserTable(Table):
 | 
			
		||||
@@ -10,6 +10,10 @@ class AdminUserTable(Table):
 | 
			
		||||
    email = Col('Email', column_html_attrs={'class': 'email'})
 | 
			
		||||
    role_id = Col('Role', column_html_attrs={'class': 'role'})
 | 
			
		||||
    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):
 | 
			
		||||
@@ -17,11 +21,12 @@ class AdminUserItem(object):
 | 
			
		||||
    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.email = email
 | 
			
		||||
        self.role_id = role_id
 | 
			
		||||
        self.confirmed = confirmed
 | 
			
		||||
        self.id = id
 | 
			
		||||
 | 
			
		||||
        if self.role_id == 1:
 | 
			
		||||
            self.role_id = 'User'
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										75
									
								
								app/templates/admin/admin_user_page.html.j2
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								app/templates/admin/admin_user_page.html.j2
									
									
									
									
									
										Normal 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 %}
 | 
			
		||||
@@ -95,7 +95,7 @@
 | 
			
		||||
        {% if current_user.is_administrator() %} <!-- Shows only for admins -->
 | 
			
		||||
          <li><div class="divider"></div></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 %}
 | 
			
		||||
      </ul>
 | 
			
		||||
    </header>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user