From b840746fed7659956654d9fb663c5fd7b58a39c5 Mon Sep 17 00:00:00 2001
From: Patrick Jentsch <p.jentsch@uni-bielefeld.de>
Date: Fri, 23 Oct 2020 10:17:14 +0200
Subject: [PATCH] Rework admin package

---
 web/app/admin/views.py                    | 20 +++---
 web/app/static/js/nopaque.lists.js        |  4 +-
 web/app/templates/admin/edit_user.html.j2 | 46 ++++++++------
 web/app/templates/admin/index.html.j2     | 42 -------------
 web/app/templates/admin/user.html.j2      | 74 +++++++++++++----------
 web/app/templates/admin/users.html.j2     | 48 +++++++++++++++
 web/app/templates/main/news.html.j2       |  1 +
 web/app/templates/nopaque.html.j2         |  2 +-
 8 files changed, 129 insertions(+), 108 deletions(-)
 delete mode 100644 web/app/templates/admin/index.html.j2
 create mode 100644 web/app/templates/admin/users.html.j2

diff --git a/web/app/admin/views.py b/web/app/admin/views.py
index e8d0d916..3046a63c 100644
--- a/web/app/admin/views.py
+++ b/web/app/admin/views.py
@@ -8,10 +8,10 @@ from ..models import Role, User
 from ..profile import tasks as profile_tasks
 
 
-@admin.route('/')
+@admin.route('/users')
 @login_required
 @admin_required
-def index():
+def users():
     users = User.query.all()
     users = [dict(username=u.username,
                   email=u.email,
@@ -19,21 +19,18 @@ def index():
                   confirmed=u.confirmed,
                   id=u.id)
              for u in users]
-    return render_template('admin/index.html.j2',
-                           title='Administration tools',
-                           users=users)
+    return render_template('admin/users.html.j2', title='Users', users=users)
 
 
-@admin.route('/user/<int:user_id>')
+@admin.route('/users/<int:user_id>')
 @login_required
 @admin_required
 def user(user_id):
     user = User.query.get_or_404(user_id)
-    return render_template('admin/user.html.j2', title='Administration: User',
-                           user=user)
+    return render_template('admin/user.html.j2', title='Edit user', user=user)
 
 
-@admin.route('/user/<int:user_id>/delete')
+@admin.route('/users/<int:user_id>/delete')
 @login_required
 @admin_required
 def delete_user(user_id):
@@ -42,7 +39,7 @@ def delete_user(user_id):
     return redirect(url_for('admin.index'))
 
 
-@admin.route('/user/<int:user_id>/edit', methods=['GET', 'POST'])
+@admin.route('/users/<int:user_id>/edit', methods=['GET', 'POST'])
 @login_required
 @admin_required
 def edit_user(user_id):
@@ -63,4 +60,5 @@ def edit_user(user_id):
     edit_user_form.role.data = user.role_id
     return render_template('admin/edit_user.html.j2',
                            edit_user_form=edit_user_form,
-                           title='Administration: Edit user', user=user)
+                           title='Edit user',
+                           user=user)
diff --git a/web/app/static/js/nopaque.lists.js b/web/app/static/js/nopaque.lists.js
index d91186dc..603f81b1 100644
--- a/web/app/static/js/nopaque.lists.js
+++ b/web/app/static/js/nopaque.lists.js
@@ -131,11 +131,11 @@ RessourceList.dataMappers = {
     confirmed: user.confirmed,
     email: user.email,
     id: user.id,
-    link: `user/${user.id}`,
+    link: `users/${user.id}`,
     role_id: user.role_id,
     username: user.username,
     username2: user.username,
-    "delete-link": `/admin/user/${user.id}/delete`,
+    "delete-link": `/admin/users/${user.id}/delete`,
     "delete-modal": `delete-user-${user.id}-modal`,
     "delete-modal-trigger": `delete-user-${user.id}-modal`,
   }),
diff --git a/web/app/templates/admin/edit_user.html.j2 b/web/app/templates/admin/edit_user.html.j2
index 3a48adf8..6e47db5f 100644
--- a/web/app/templates/admin/edit_user.html.j2
+++ b/web/app/templates/admin/edit_user.html.j2
@@ -1,27 +1,35 @@
 {% extends "nopaque.html.j2" %}
+{% import 'materialize/wtf.html.j2' as wtf %}
 
 {% block page_content %}
-<div class="col s12 m4">
-  <h3 id="title">{{ user.username }}</h3>
-  <p id="description">Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren,</p>
-  <a class="waves-effect waves-light btn" href="{{ url_for('admin.user', user_id=user.id) }}"><i class="material-icons left">arrow_back</i>Back to user administration</a>
-</div>
+<div class="container">
+  <div class="row">
+    <div class="col s12">
+      <h1 id="title">Edit user</h1>
+    </div>
 
-<div class="col s12 m8">
-  <div class="card">
-    <form method="POST">
-      <div class="card-content">
-        {{ edit_user_form.hidden_tag() }}
-        {{ M.render_field(edit_user_form.username, data_length='64', material_icon='account_circle') }}
-        {{ M.render_field(edit_user_form.email, class_='validate', material_icon='email', type='email') }}
-        {{ M.render_field(edit_user_form.role, material_icon='swap_vert') }}
-        {{ M.render_field(edit_user_form.confirmed, material_icon='check') }}
-      </div>
-      <div class="card-action right-align">
-        {{ M.render_field(edit_user_form.submit, material_icon='send') }}
+    <div class="col s12 m4">
+      <h2>{{ user.username }}</h2>
+      <p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren,</p>
+      <a class="waves-effect waves-light btn" href="{{ url_for('.user', user_id=user.id) }}"><i class="material-icons left">arrow_back</i>Back to user administration</a>
+    </div>
+
+    <div class="col s12 m8">
+      <div class="card">
+        <form method="POST">
+          <div class="card-content">
+            {{ edit_user_form.hidden_tag() }}
+            {{ wtf.render_field(edit_user_form.username, data_length='64', material_icon='account_circle') }}
+            {{ wtf.render_field(edit_user_form.email, class_='validate', material_icon='email', type='email') }}
+            {{ wtf.render_field(edit_user_form.role, material_icon='swap_vert') }}
+            {{ wtf.render_field(edit_user_form.confirmed, material_icon='check') }}
+          </div>
+          <div class="card-action right-align">
+            {{ wtf.render_field(edit_user_form.submit, material_icon='send') }}
+          </div>
+        </form>
       </div>
-    </form>
+    </div>
   </div>
 </div>
-
 {% endblock %}
diff --git a/web/app/templates/admin/index.html.j2 b/web/app/templates/admin/index.html.j2
deleted file mode 100644
index 9fca5b58..00000000
--- a/web/app/templates/admin/index.html.j2
+++ /dev/null
@@ -1,42 +0,0 @@
-{% extends "nopaque.html.j2" %}
-
-{% set full_width = True %}
-
-{% block page_content %}
-<div class="col s12">
-  <div class="card">
-    <div class="card-content" id="users">
-      <span class="card-title">User list</span>
-      <div class="input-field">
-        <i class="material-icons prefix">search</i>
-        <input id="search-user" class="search" type="search"></input>
-        <label for="search-user">Search user</label>
-      </div>
-      <ul class="pagination paginationTop"></ul>
-      <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 type="module">
-import {RessourceList} from '../../static/js/nopaque.lists.js';
-let userList = new RessourceList('users', null, "User", RessourceList.options.extended);
-document.addEventListener("DOMContentLoaded", () => {
-  userList._add({{ users|tojson|safe }});
-});
-</script>
-{% endblock %}
diff --git a/web/app/templates/admin/user.html.j2 b/web/app/templates/admin/user.html.j2
index c1e53a18..c66d1fdc 100644
--- a/web/app/templates/admin/user.html.j2
+++ b/web/app/templates/admin/user.html.j2
@@ -1,34 +1,40 @@
 {% extends "nopaque.html.j2" %}
 
 {% block page_content %}
-<div class="col s12 m4">
-  <h3 id="title">{{ user.username }}</h3>
-  <p id="description">Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren,</p>
-  <a class="waves-effect waves-light btn" href="{{ url_for('admin.index') }}"><i class="material-icons left">arrow_back</i>Back to admin board</a>
-</div>
+<div class="container">
+  <div class="row">
+    <div class="col s12">
+      <h1>{{ title }}</h1>
+    </div>
 
-<div class="col s12 m8">
-  <div class="card">
-    <div class="card-content">
-      <span class="card-title">User information</span>
-      <ul>
-        <li>Username: {{ user.username }}</li>
-        <li>Email: {{ user.email }}</li>
-        <li>ID: {{ user.id }}</li>
-        <li>Member since: {{ user.member_since.strftime('%m/%d/%Y, %H:%M:%S %p') }}</li>
-        <li>Confirmed status: {{ user.confirmed }}</li>
-        <li>Last seen: {{ user.last_seen.strftime('%m/%d/%Y, %H:%M:%S %p') }}</li>
-        <li>Role ID: {{ user.role_id }}</li>
-        <li>Permissions as Int: {{ user.role.permissions }}</li>
-        <li>Role name: {{ user.role.name }}</li>
-      </ul>
+    <div class="col s12 m4">
+      <h2>{{ user.username }}</h2>
+      <p id="description">Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren,</p>
+      <a class="waves-effect waves-light btn" href="{{ url_for('.users') }}"><i class="material-icons left">arrow_back</i>Back to Users</a>
     </div>
-    <div class="card-action right-align">
-      <a href="{{ url_for('admin.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 class="col s12 m8">
+      <div class="card">
+        <div class="card-content">
+          <span class="card-title">User information</span>
+          <ul>
+            <li>Username: {{ user.username }}</li>
+            <li>Email: {{ user.email }}</li>
+            <li>ID: {{ user.id }}</li>
+            <li>Member since: {{ user.member_since.strftime('%m/%d/%Y, %H:%M:%S %p') }}</li>
+            <li>Confirmed status: {{ user.confirmed }}</li>
+            <li>Last seen: {{ user.last_seen.strftime('%m/%d/%Y, %H:%M:%S %p') }}</li>
+            <li>Role ID: {{ user.role_id }}</li>
+            <li>Permissions as Int: {{ user.role.permissions }}</li>
+            <li>Role name: {{ user.role.name }}</li>
+          </ul>
+        </div>
+        <div class="card-action right-align">
+          <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>
     </div>
-  </div>
-</div>
 
 <div class="col s12 l6">
   <h3>Corpora</h3>
@@ -92,21 +98,23 @@
 <!-- Modals -->
 <div id="delete-user-modal" class="modal">
   <div class="modal-content">
-    <h4>Confirm user deletion</h4>
+    <h3>Delete user</h3>
     <p>Do you really want to delete the user {{ user.username }}? All associated data will be permanently deleted!</p>
   </div>
   <div class="modal-footer">
     <a href="#!" class="modal-close waves-effect waves-light btn">Cancel</a>
-    <a href="{{ url_for('admin.delete_user', user_id=user.id) }}" class="modal-close waves-effect waves-light btn red"><i class="material-icons left">delete</i>Delete</a>
+    <a href="{{ url_for('.delete_user', user_id=user.id) }}" class="modal-close waves-effect waves-light btn red"><i class="material-icons left">delete</i>Delete</a>
   </div>
 </div>
+{% endblock %}
 
+
+{% block scripts %}
+{{ super() }}
 <script type="module">
-import {RessourceList} from '../../static/js/nopaque.lists.js';
-let corpusList = new RessourceList("corpora", nopaque.foreignCorporaSubscribers, "Corpus");
-let jobList = new RessourceList("jobs", nopaque.foreignJobsSubscribers, "Job");
-document.addEventListener("DOMContentLoaded", () => {
+  import {RessourceList} from '{{ url_for('static', filename='js/nopaque.lists.js') }}';
+  let corpusList = new RessourceList("corpora", nopaque.foreignCorporaSubscribers, "Corpus");
+  let jobList = new RessourceList("jobs", nopaque.foreignJobsSubscribers, "Job");
   nopaque.socket.emit("foreign_user_data_stream_init", {{ user.id }});
-  });
 </script>
-{% endblock %}
+{% endblock scripts %}
diff --git a/web/app/templates/admin/users.html.j2 b/web/app/templates/admin/users.html.j2
new file mode 100644
index 00000000..022f7e5c
--- /dev/null
+++ b/web/app/templates/admin/users.html.j2
@@ -0,0 +1,48 @@
+{% extends "nopaque.html.j2" %}
+
+{% block page_content %}
+<div class="container">
+  <div class="row">
+    <div class="col s12">
+      <h1>{{ title }}</h1>
+    </div>
+
+    <div class="col s12">
+      <div class="card">
+        <div class="card-content" id="users">
+          <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">
+            <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>
+  </div>
+</div>
+{% endblock %}
+
+{% 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>
+{% endblock scripts %}
diff --git a/web/app/templates/main/news.html.j2 b/web/app/templates/main/news.html.j2
index cf3d9653..968e0f1b 100644
--- a/web/app/templates/main/news.html.j2
+++ b/web/app/templates/main/news.html.j2
@@ -6,6 +6,7 @@
     <div class="col s12">
       <h1>{{ title }}</h1>
     </div>
+
     <div class="col s12">
       <div class="card" id="beta-launch">
         <div class="card-content">
diff --git a/web/app/templates/nopaque.html.j2 b/web/app/templates/nopaque.html.j2
index 0437c29a..c9097dd1 100644
--- a/web/app/templates/nopaque.html.j2
+++ b/web/app/templates/nopaque.html.j2
@@ -136,7 +136,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.index') }}"><i class="material-icons">build</i>Administration tools</a></li>
+  <li><a href="{{ url_for('admin.users') }}"><i class="material-icons">build</i>Administration tools</a></li>
   {% endif %}
 </ul>
 {% endblock sidenav %}
-- 
GitLab