mirror of
				https://gitlab.ub.uni-bielefeld.de/sfb1288inf/nopaque.git
				synced 2025-11-03 20:02:47 +00:00 
			
		
		
		
	Unify more tables
This commit is contained in:
		@@ -1,45 +0,0 @@
 | 
			
		||||
from flask_table import Table, Col, LinkCol
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AdminUserTable(Table):
 | 
			
		||||
    '''
 | 
			
		||||
    Declares the table describing colum by column.
 | 
			
		||||
    '''
 | 
			
		||||
    classes = ['highlight', 'responsive-table']
 | 
			
		||||
    username = Col('Username', column_html_attrs={'class': 'username'},
 | 
			
		||||
                   th_html_attrs={'class': 'sort',
 | 
			
		||||
                                  'data-sort': 'username'})
 | 
			
		||||
    email = Col('Email', column_html_attrs={'class': 'email'},
 | 
			
		||||
                th_html_attrs={'class': 'sort',
 | 
			
		||||
                               'data-sort': 'email'})
 | 
			
		||||
    role_id = Col('Role', column_html_attrs={'class': 'role'},
 | 
			
		||||
                  th_html_attrs={'class': 'sort',
 | 
			
		||||
                                 'data-sort': 'role'})
 | 
			
		||||
    confirmed = Col('Confrimed Status', column_html_attrs={'class': 'confirmed'},  # noqa
 | 
			
		||||
                    th_html_attrs={'class': 'sort',
 | 
			
		||||
                                   'data-sort': 'confirmed'})
 | 
			
		||||
    id = Col('User Id', column_html_attrs={'class': 'id'},
 | 
			
		||||
             th_html_attrs={'class': 'sort',
 | 
			
		||||
                            'data-sort': 'id'})
 | 
			
		||||
    url = LinkCol('Profile', 'admin.user',
 | 
			
		||||
                  url_kwargs=dict(user_id='id'),
 | 
			
		||||
                  anchor_attrs={'class': 'waves-effect waves-light btn-floating'},  # noqa
 | 
			
		||||
                  text_fallback='<i class="material-icons">edit</i>')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AdminUserItem(object):
 | 
			
		||||
    '''
 | 
			
		||||
    Describes one item like one row per table.
 | 
			
		||||
    '''
 | 
			
		||||
 | 
			
		||||
    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'
 | 
			
		||||
        elif self.role_id == 2:
 | 
			
		||||
            self.role_id = 'Admin'
 | 
			
		||||
@@ -2,12 +2,10 @@ from flask import flash, redirect, render_template, url_for
 | 
			
		||||
from flask_login import login_required
 | 
			
		||||
from . import admin
 | 
			
		||||
from .forms import EditUserForm
 | 
			
		||||
from .tables import AdminUserItem, AdminUserTable
 | 
			
		||||
from .. import db
 | 
			
		||||
from ..decorators import admin_required
 | 
			
		||||
from ..models import Role, User
 | 
			
		||||
from ..profile import tasks as profile_tasks
 | 
			
		||||
import html
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@admin.route('/')
 | 
			
		||||
@@ -15,14 +13,15 @@ import html
 | 
			
		||||
@admin_required
 | 
			
		||||
def index():
 | 
			
		||||
    users = User.query.all()
 | 
			
		||||
    items = [AdminUserItem(u.username, u.email, u.role_id, u.confirmed, u.id)
 | 
			
		||||
    users = [dict(username=u.username,
 | 
			
		||||
                  email=u.email,
 | 
			
		||||
                  role_id=u.role_id,
 | 
			
		||||
                  confirmed=u.confirmed,
 | 
			
		||||
                  id=u.id)
 | 
			
		||||
             for u in users]
 | 
			
		||||
    # Convert table object to html string
 | 
			
		||||
    table = html.unescape(AdminUserTable(items).__html__())
 | 
			
		||||
    # Add class "list" to tbody element. Needed for "List.js"
 | 
			
		||||
    table = table.replace('tbody', 'tbody class="list"', 1)
 | 
			
		||||
    return render_template('admin/index.html.j2', table=table,
 | 
			
		||||
                           title='Administration tools')
 | 
			
		||||
    return render_template('admin/index.html.j2',
 | 
			
		||||
                           title='Administration tools',
 | 
			
		||||
                           users=users)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@admin.route('/user/<int:user_id>')
 | 
			
		||||
@@ -38,7 +37,6 @@ def user(user_id):
 | 
			
		||||
@login_required
 | 
			
		||||
@admin_required
 | 
			
		||||
def delete_user(user_id):
 | 
			
		||||
    user = User.query.get_or_404(user_id)
 | 
			
		||||
    profile_tasks.delete_user(user_id)
 | 
			
		||||
    flash('User has been deleted!')
 | 
			
		||||
    return redirect(url_for('admin.index'))
 | 
			
		||||
 
 | 
			
		||||
@@ -1,65 +0,0 @@
 | 
			
		||||
from flask_table import Table, Col, DatetimeCol, LinkCol
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ResultTable(Table):
 | 
			
		||||
    '''
 | 
			
		||||
    Declares the Table showing results. Declaration is column by column.
 | 
			
		||||
    '''
 | 
			
		||||
    classes = ['highlight', 'responsive-table']
 | 
			
		||||
    query = Col('Query', column_html_attrs={'class': 'query'},
 | 
			
		||||
                th_html_attrs={'class': 'sort',
 | 
			
		||||
                               'data-sort': 'query'})
 | 
			
		||||
    match_count = Col('Match count', column_html_attrs={'class':
 | 
			
		||||
                                                        'match-count'},
 | 
			
		||||
                      th_html_attrs={'class': 'sort',
 | 
			
		||||
                                     'data-sort': 'match-count'})
 | 
			
		||||
    corpus_name = Col('Corpus name', column_html_attrs={'class':
 | 
			
		||||
                                                        'corpus-name'},
 | 
			
		||||
                      th_html_attrs={'class': 'sort',
 | 
			
		||||
                                     'data-sort': 'corpus-name'})
 | 
			
		||||
    corpus_creation_date = DatetimeCol('Corpus creation date',
 | 
			
		||||
                                       column_html_attrs={'class':
 | 
			
		||||
                                                         'corpus-creation-  date'},  # noqa
 | 
			
		||||
                                       th_html_attrs={'class': 'sort',
 | 
			
		||||
                                                      'data-sort':
 | 
			
		||||
                                                      'corpus-creation-date'},
 | 
			
		||||
                                       datetime_format='dd/MM/yyyy, HH:mm:ss a')  # noqa
 | 
			
		||||
    corpus_analysis_date = DatetimeCol('Date of result creation',
 | 
			
		||||
                                       column_html_attrs={'class':
 | 
			
		||||
                                                          'corpus-analysis-data'},  # noqa
 | 
			
		||||
                                       th_html_attrs={'class': 'sort',
 | 
			
		||||
                                                      'data-sort':
 | 
			
		||||
                                                      'corpus-analysis-data'},
 | 
			
		||||
                                       datetime_format='dd/MM/yyyy, HH:mm:ss a')  # noqa
 | 
			
		||||
    corpus_type = Col('Result Type',
 | 
			
		||||
                      column_html_attrs={'class':
 | 
			
		||||
                                         'corpus-type'},
 | 
			
		||||
                      th_html_attrs={'class': 'sort',
 | 
			
		||||
                                     'data-sort':
 | 
			
		||||
                                     'corpus-type'})
 | 
			
		||||
    details = LinkCol('Details', 'results.result_details',
 | 
			
		||||
                      url_kwargs=dict(result_id='id'),
 | 
			
		||||
                      anchor_attrs={'class': 'waves-effect waves-light btn-floating'},  # noqa
 | 
			
		||||
                      text_fallback='<i class="material-icons">info_outline</i>')  # noqa
 | 
			
		||||
    inspect = LinkCol('Inspect', 'results.result_inspect',
 | 
			
		||||
                      url_kwargs=dict(result_id='id'),
 | 
			
		||||
                      anchor_attrs={'class': 'waves-effect waves-light btn-floating'},  # noqa
 | 
			
		||||
                      text_fallback='<i class="material-icons">search</i>')  # noqa
 | 
			
		||||
    # TODO: Maybe somehow fix taht there are two columns fpr two action buttons
 | 
			
		||||
    # Or maybe just get rid of flask tables?
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ResultItem(object):
 | 
			
		||||
    '''
 | 
			
		||||
    Describes one result item row.
 | 
			
		||||
    '''
 | 
			
		||||
 | 
			
		||||
    def __init__(self, query, match_count, corpus_name, corpus_creation_date,
 | 
			
		||||
                 corpus_analysis_date, corpus_type, id):
 | 
			
		||||
        self.query = query
 | 
			
		||||
        self.match_count = match_count
 | 
			
		||||
        self.corpus_name = corpus_name
 | 
			
		||||
        self.corpus_creation_date = corpus_creation_date
 | 
			
		||||
        self.corpus_analysis_date = corpus_analysis_date
 | 
			
		||||
        self.corpus_type = corpus_type
 | 
			
		||||
        self.id = id
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
class RessourceList extends List {
 | 
			
		||||
  constructor(idOrElement, subscriberList, type, options={}) {
 | 
			
		||||
    if (!["corpus", "job", "result"].includes(type)) {
 | 
			
		||||
    if (!["corpus", "job", "result", "user"].includes(type)) {
 | 
			
		||||
      console.error("Unknown Type!");
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
@@ -77,15 +77,21 @@ RessourceList.dataMapper = {
 | 
			
		||||
                service: job.service,
 | 
			
		||||
                status: job.status,
 | 
			
		||||
                title: job.title}),
 | 
			
		||||
  result : result => ({ query: result.query,
 | 
			
		||||
                        match_count: result.match_count,
 | 
			
		||||
                        corpus_name: result.corpus_name,
 | 
			
		||||
                        corpus_creation_date: result.corpus_creation_date,
 | 
			
		||||
                        corpus_analysis_date: result.corpus_analysis_date,
 | 
			
		||||
                        corpus_type : result.corpus_type,
 | 
			
		||||
                        "details-link": `${result.id}/details`,
 | 
			
		||||
                        "inspect-link": `${result.id}/inspect`,
 | 
			
		||||
                        "delete-modal": `delete-result-${result.id}-modal`})
 | 
			
		||||
  result: result => ({ query: result.query,
 | 
			
		||||
                       match_count: result.match_count,
 | 
			
		||||
                       corpus_name: result.corpus_name,
 | 
			
		||||
                       corpus_creation_date: result.corpus_creation_date,
 | 
			
		||||
                       corpus_analysis_date: result.corpus_analysis_date,
 | 
			
		||||
                       corpus_type : result.corpus_type,
 | 
			
		||||
                       "details-link": `${result.id}/details`,
 | 
			
		||||
                       "inspect-link": `${result.id}/inspect`,
 | 
			
		||||
                       "delete-modal": `delete-result-${result.id}-modal`}),
 | 
			
		||||
  user: user => ({username: user.username,
 | 
			
		||||
                  email: user.email,
 | 
			
		||||
                  role_id: user.role_id,
 | 
			
		||||
                  confirmed: user.confirmed,
 | 
			
		||||
                  id: user.id,
 | 
			
		||||
                  "profile-link": `user/${user.id}`})
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -157,32 +163,48 @@ RessourceList.options = {
 | 
			
		||||
                     {name: "link", attr: "href"},
 | 
			
		||||
                     {name: "service", attr: "data-service"},
 | 
			
		||||
                     {name: "status", attr: "data-status"}]},
 | 
			
		||||
  result : {item: `<tr>
 | 
			
		||||
                     <td class="query"></td>
 | 
			
		||||
                     <td class="match_count"></td>
 | 
			
		||||
                     <td class="corpus_name"></td>
 | 
			
		||||
                     <td class="corpus_creation_date"></td>
 | 
			
		||||
                     <td class="corpus_analysis_date"></td>
 | 
			
		||||
                     <td class="corpus_type"></td>
 | 
			
		||||
                     <td class="actions right-align">
 | 
			
		||||
  result: {item: `<tr>
 | 
			
		||||
                    <td class="query"></td>
 | 
			
		||||
                    <td class="match_count"></td>
 | 
			
		||||
                    <td class="corpus_name"></td>
 | 
			
		||||
                    <td class="corpus_creation_date"></td>
 | 
			
		||||
                    <td class="corpus_analysis_date"></td>
 | 
			
		||||
                    <td class="corpus_type"></td>
 | 
			
		||||
                    <td class="actions right-align">
 | 
			
		||||
                      <a class="btn-floating details-link waves-effect waves-light"><i class="material-icons">info_outline</i>
 | 
			
		||||
                      </a>
 | 
			
		||||
                      <a class="btn-floating inspect-link waves-effect waves-light"><i class="material-icons">search</i>
 | 
			
		||||
                      </a>
 | 
			
		||||
                      <a class="btn-floating red delete-modal waves-effect waves-light modal-trigger"><i class="material-icons">delete</i>
 | 
			
		||||
                      </a>
 | 
			
		||||
                     </td>
 | 
			
		||||
                   </tr>`,
 | 
			
		||||
            valueNames: ["query",
 | 
			
		||||
                         "match_count",
 | 
			
		||||
                         "corpus_name",
 | 
			
		||||
                         "corpus_creation_date",
 | 
			
		||||
                         "corpus_analysis_date",
 | 
			
		||||
                         "corpus_type",
 | 
			
		||||
                         {name: "details-link", attr: "href"},
 | 
			
		||||
                         {name: "inspect-link", attr: "href"},
 | 
			
		||||
                         {name: "delete-modal", attr: "data-target"}]
 | 
			
		||||
            }
 | 
			
		||||
                    </td>
 | 
			
		||||
                  </tr>`,
 | 
			
		||||
           valueNames: ["query",
 | 
			
		||||
                        "match_count",
 | 
			
		||||
                        "corpus_name",
 | 
			
		||||
                        "corpus_creation_date",
 | 
			
		||||
                        "corpus_analysis_date",
 | 
			
		||||
                        "corpus_type",
 | 
			
		||||
                        {name: "details-link", attr: "href"},
 | 
			
		||||
                        {name: "inspect-link", attr: "href"},
 | 
			
		||||
                        {name: "delete-modal", attr: "data-target"}]},
 | 
			
		||||
  user: {item: `<tr>
 | 
			
		||||
                  <td class="username"></td>
 | 
			
		||||
                  <td class="email"></td>
 | 
			
		||||
                  <td class="role_id"></td>
 | 
			
		||||
                  <td class="confirmed"></td>
 | 
			
		||||
                  <td class="id"></td>
 | 
			
		||||
                  <td class="actions">
 | 
			
		||||
                  <a class="btn-floating profile-link waves-effect waves-light"><i class="material-icons">edit</i>
 | 
			
		||||
                  </a>
 | 
			
		||||
                  </td>
 | 
			
		||||
                </tr>`,
 | 
			
		||||
         valueNames: ["username",
 | 
			
		||||
                      "email",
 | 
			
		||||
                      "role_id",
 | 
			
		||||
                      "confirmed",
 | 
			
		||||
                      "id",
 | 
			
		||||
                      {name: "profile-link", attr: "href"}]}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -13,28 +13,28 @@
 | 
			
		||||
        <label for="search-user">Search user</label>
 | 
			
		||||
      </div>
 | 
			
		||||
      <ul class="pagination paginationTop"></ul>
 | 
			
		||||
      {{ table }}
 | 
			
		||||
      <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>
 | 
			
		||||
  var options = {page: 10,
 | 
			
		||||
                 pagination: [
 | 
			
		||||
                 {
 | 
			
		||||
                   name: "paginationTop",
 | 
			
		||||
                   paginationClass: "paginationTop",
 | 
			
		||||
                   innerWindow: 8,
 | 
			
		||||
                   outerWindow: 1
 | 
			
		||||
                 },
 | 
			
		||||
                 {
 | 
			
		||||
                    paginationClass: "paginationBottom",
 | 
			
		||||
                    innerWindow: 8,
 | 
			
		||||
                    outerWindow: 1
 | 
			
		||||
                  }
 | 
			
		||||
                 ],
 | 
			
		||||
                 valueNames: ['username', 'email', 'role', 'confirmed', 'id']};
 | 
			
		||||
  var userList = new List('users', options);
 | 
			
		||||
  var ressources = {{ users|tojson|safe }};
 | 
			
		||||
  var userList = new RessourceList('users', null, "user");
 | 
			
		||||
  userList.addRessources(ressources);
 | 
			
		||||
</script>
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 
 | 
			
		||||
@@ -84,3 +84,16 @@
 | 
			
		||||
    {% endif %}
 | 
			
		||||
  </button>
 | 
			
		||||
{% endmacro %}
 | 
			
		||||
 | 
			
		||||
{% macro delete_modal_file(file) %}
 | 
			
		||||
<div id="delete-corpus-file-{{ file.id }}-modal" class="modal">
 | 
			
		||||
  <div class="modal-content">
 | 
			
		||||
    <h4>Confirm corpus file deletion</h4>
 | 
			
		||||
    <p>Do you really want to delete the corpus file {{ file.filename }}? The file will be permanently deleted!</p>
 | 
			
		||||
  </div>
 | 
			
		||||
  <div class="modal-footer">
 | 
			
		||||
    <a href="#!" class="btn modal-close waves-effect waves-light">Cancel</a>
 | 
			
		||||
    <a class="btn modal-close red waves-effect waves-light" href="{{ url_for('corpora.delete_corpus_file', corpus_file_id=resource_id, corpus_id=corpus.id) }}"><i class="material-icons left">delete</i>Delete</a>
 | 
			
		||||
  </div>
 | 
			
		||||
</div>
 | 
			
		||||
{% endmacro %}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user