diff --git a/web/app/admin/tables.py b/web/app/admin/tables.py deleted file mode 100644 index 52196784..00000000 --- a/web/app/admin/tables.py +++ /dev/null @@ -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' diff --git a/web/app/admin/views.py b/web/app/admin/views.py index f06cf098..e8d0d916 100644 --- a/web/app/admin/views.py +++ b/web/app/admin/views.py @@ -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')) diff --git a/web/app/results/tables.py b/web/app/results/tables.py deleted file mode 100644 index e69de29b..00000000 diff --git a/web/app/services/tables.py b/web/app/services/tables.py deleted file mode 100644 index e9d9389c..00000000 --- a/web/app/services/tables.py +++ /dev/null @@ -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 diff --git a/web/app/static/js/nopaque.lists.js b/web/app/static/js/nopaque.lists.js index 04145c2e..2c3aeb6c 100644 --- a/web/app/static/js/nopaque.lists.js +++ b/web/app/static/js/nopaque.lists.js @@ -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"}]} }; diff --git a/web/app/templates/admin/index.html.j2 b/web/app/templates/admin/index.html.j2 index 7c85c715..0117caff 100644 --- a/web/app/templates/admin/index.html.j2 +++ b/web/app/templates/admin/index.html.j2 @@ -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 %} diff --git a/web/app/templates/macros/materialize.html.j2 b/web/app/templates/macros/materialize.html.j2 index bf14c6e7..3ba6b855 100644 --- a/web/app/templates/macros/materialize.html.j2 +++ b/web/app/templates/macros/materialize.html.j2 @@ -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 %}