From a8643aa9f4437eb8bb1fac90e701215507066ac3 Mon Sep 17 00:00:00 2001
From: Patrick Jentsch <p.jentsch@uni-bielefeld.de>
Date: Wed, 13 Jan 2021 11:57:46 +0100
Subject: [PATCH] Add Breadcrumbs and UserList to admin package

---
 web/app/admin/views.py                        | 20 ++++++++++-----
 web/app/templates/admin/_breadcrumbs.html.j2  | 19 ++++++++++++++
 ...ral_settings.html.j2 => edit_user.html.j2} |  4 +++
 web/app/templates/admin/user.html.j2          |  6 ++++-
 web/app/templates/admin/users.html.j2         | 25 +++++++++++--------
 web/app/templates/nopaque.html.j2             |  3 ++-
 6 files changed, 58 insertions(+), 19 deletions(-)
 create mode 100644 web/app/templates/admin/_breadcrumbs.html.j2
 rename web/app/templates/admin/{edit_general_settings.html.j2 => edit_user.html.j2} (96%)

diff --git a/web/app/admin/views.py b/web/app/admin/views.py
index 798c0df8..7f62d4a9 100644
--- a/web/app/admin/views.py
+++ b/web/app/admin/views.py
@@ -8,11 +8,19 @@ from ..models import Role, User
 from ..settings import tasks as settings_tasks
 
 
+@admin.route('/')
+@login_required
+@admin_required
+def index():
+    return redirect(url_for('.users'))
+
+
 @admin.route('/users')
 @login_required
 @admin_required
 def users():
-    users = [user.to_dict() for user in User.query.all()]
+    # users = [user.to_dict() for user in User.query.all()]
+    users = {user.id: user.to_dict() for user in User.query.all()}
     return render_template('admin/users.html.j2', title='Users', users=users)
 
 
@@ -33,10 +41,10 @@ def delete_user(user_id):
     return redirect(url_for('.users'))
 
 
-@admin.route('/users/<int:user_id>/edit_general_settings', methods=['GET', 'POST'])  # noqa
+@admin.route('/users/<int:user_id>/edit', methods=['GET', 'POST'])  # noqa
 @login_required
 @admin_required
-def edit_general_settings(user_id):
+def edit_user(user_id):
     user = User.query.get_or_404(user_id)
     form = EditGeneralSettingsAdminForm(user=user)
     if form.validate_on_submit():
@@ -47,11 +55,11 @@ def edit_general_settings(user_id):
         user.role = Role.query.get(form.role.data)
         db.session.commit()
         flash('Settings have been updated.')
-        return redirect(url_for('.edit_general_settings', user_id=user.id))
+        return redirect(url_for('.edit_user', user_id=user.id))
     form.confirmed.data = user.confirmed
     form.dark_mode.data = user.setting_dark_mode
     form.email.data = user.email
     form.role.data = user.role_id
     form.username.data = user.username
-    return render_template('admin/edit_general_settings.html.j2',
-                           form=form, title='General settings', user=user)
+    return render_template('admin/edit_user.html.j2', form=form,
+                           title='Edit user', user=user)
diff --git a/web/app/templates/admin/_breadcrumbs.html.j2 b/web/app/templates/admin/_breadcrumbs.html.j2
new file mode 100644
index 00000000..d27940c3
--- /dev/null
+++ b/web/app/templates/admin/_breadcrumbs.html.j2
@@ -0,0 +1,19 @@
+<ul class="tabs tabs-transparent">
+  <li class="tab"><a href="{{ url_for('main.index') }}" target="_self"><i class="material-icons">home</i></a></li>
+  <li class="tab disabled"><i class="material-icons">navigate_next</i></li>
+  <li class="tab"><a href="{{ url_for('.index') }}" target="_self">Administration</a></li>
+  <li class="tab disabled"><i class="material-icons">navigate_next</i></li>
+  {% if request.path == url_for('.users') %}
+  <li class="tab"><a class="active" href="{{ url_for('.users') }}" target="_self">Users</a></li>
+  {% elif request.path == url_for('.user', user_id=user.id) %}
+  <li class="tab"><a href="{{ url_for('.users') }}" target="_self">Users</a></li>
+  <li class="tab disabled"><i class="material-icons">navigate_next</i></li>
+  <li class="tab"><a class="active" href="{{ url_for('.user', user_id=user.id) }}" target="_self">{{ user.username }}</a></li>
+  {% elif request.path == url_for('.edit_user', user_id=user.id) %}
+  <li class="tab"><a href="{{ url_for('.users') }}" target="_self">Users</a></li>
+  <li class="tab disabled"><i class="material-icons">navigate_next</i></li>
+  <li class="tab"><a href="{{ url_for('.user', user_id=user.id) }}" target="_self">{{ user.username }}</a></li>
+  <li class="tab disabled"><i class="material-icons">navigate_next</i></li>
+  <li class="tab"><a class="active" href="{{ url_for('.edit_user', user_id=user.id) }}" target="_self">Edit</a></li>
+  {% endif %}
+</ul>
diff --git a/web/app/templates/admin/edit_general_settings.html.j2 b/web/app/templates/admin/edit_user.html.j2
similarity index 96%
rename from web/app/templates/admin/edit_general_settings.html.j2
rename to web/app/templates/admin/edit_user.html.j2
index 929a867c..61ef21da 100644
--- a/web/app/templates/admin/edit_general_settings.html.j2
+++ b/web/app/templates/admin/edit_user.html.j2
@@ -1,6 +1,10 @@
 {% extends "nopaque.html.j2" %}
 {% import 'materialize/wtf.html.j2' as wtf %}
 
+{% block nav_content %}
+{% include 'admin/_breadcrumbs.html.j2' %}
+{% endblock nav_content %}
+
 {% block page_content %}
 <div class="container">
   <div class="row">
diff --git a/web/app/templates/admin/user.html.j2 b/web/app/templates/admin/user.html.j2
index 78351735..27d09d8c 100644
--- a/web/app/templates/admin/user.html.j2
+++ b/web/app/templates/admin/user.html.j2
@@ -1,5 +1,9 @@
 {% extends "nopaque.html.j2" %}
 
+{% block nav_content %}
+{% include 'admin/_breadcrumbs.html.j2' %}
+{% endblock nav_content %}
+
 {% block page_content %}
 <div class="container">
   <div class="row">
@@ -30,7 +34,7 @@
           </ul>
         </div>
         <div class="card-action right-align">
-          <a href="{{ url_for('.edit_general_settings', user_id=user.id) }}" class="waves-effect waves-light btn"><i class="material-icons left">edit</i>Edit</a>
+          <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>
diff --git a/web/app/templates/admin/users.html.j2 b/web/app/templates/admin/users.html.j2
index a7b712da..afe282ff 100644
--- a/web/app/templates/admin/users.html.j2
+++ b/web/app/templates/admin/users.html.j2
@@ -1,5 +1,9 @@
 {% extends "nopaque.html.j2" %}
 
+{% block nav_content %}
+{% include 'admin/_breadcrumbs.html.j2' %}
+{% endblock nav_content %}
+
 {% block page_content %}
 <div class="container">
   <div class="row">
@@ -7,28 +11,28 @@
       <h1 id="title">{{ title }}</h1>
     </div>
 
-    <div class="col s12">
+    <div class="col s12" id="users">
       <div class="card">
-        <div class="card-content" id="users">
+        <div class="card-content">
           <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">
+          <table class="highlight ressource-list">
             <thead>
               <tr>
                 <th class="sort" data-sort="id">Id</th>
                 <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>{# Actions #}</th>
+                <th class="sort" data-sort="last_seen">Last seen</th>
+                <th class="sort" data-sort="role">Role</th>
+                <th></th>
               </tr>
             </thead>
             <tbody class="list"></tbody>
           </table>
-          <ul class="pagination paginationBottom"></ul>
+          <ul class="pagination"></ul>
         </div>
       </div>
     </div>
@@ -38,9 +42,8 @@
 
 {% 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>
+  let userList = new UserList(document.querySelector('#users'), {page: 10});
+  userList.init({{ users|tojson }});
 </script>
 {% endblock scripts %}
diff --git a/web/app/templates/nopaque.html.j2 b/web/app/templates/nopaque.html.j2
index 73e9bc9a..c5085490 100644
--- a/web/app/templates/nopaque.html.j2
+++ b/web/app/templates/nopaque.html.j2
@@ -150,7 +150,7 @@
   {% if current_user.is_administrator() %}
   <li><div class="divider"></div></li>
   <li><a class="subheader">Administration</a></li>
-  <li><a href="{{ url_for('admin.users') }}"><i class="material-icons">build</i>Administration tools</a></li>
+  <li><a href="{{ url_for('admin.index') }}"><i class="material-icons">build</i>Administration</a></li>
   {% endif %}
 </ul>
 {% endblock sidenav %}
@@ -264,6 +264,7 @@
 <script src="{{ url_for('static', filename='js/nopaque/lists/JobInputList.js') }}"></script>
 <script src="{{ url_for('static', filename='js/nopaque/lists/JobResultList.js') }}"></script>
 <script src="{{ url_for('static', filename='js/nopaque/lists/QueryResultList.js') }}"></script>
+<script src="{{ url_for('static', filename='js/nopaque/lists/UserList.js') }}"></script>
 <script>
   // Disable all option elements with no value
   for (let optionElement of document.querySelectorAll('option[value=""]')) {optionElement.disabled = true;}
-- 
GitLab