From 923c2ff5e1d854851011712789ddeca871e43914 Mon Sep 17 00:00:00 2001
From: Benjamin Bertrand <benjamin.bertrand@esss.se>
Date: Thu, 14 Dec 2017 16:43:22 +0100
Subject: [PATCH] Move index to its own blueprint

- Main blueprint used to declare custom views for all blueprints.
(keep inventory blueprint cleaner)
- Add url_prefix to each blueprint
---
 app/factory.py                   |  8 ++++---
 app/inventory/views.py           | 24 -------------------
 app/main/__init__.py             |  0
 app/main/views.py                | 40 ++++++++++++++++++++++++++++++++
 app/static/js/attributes.js      |  2 +-
 app/static/js/hosts.js           |  4 ++--
 app/static/js/items.js           |  4 ++--
 app/templates/admin/index.html   |  2 +-
 app/templates/base.html          | 12 +++++-----
 app/templates/users/profile.html |  2 +-
 10 files changed, 58 insertions(+), 40 deletions(-)
 create mode 100644 app/main/__init__.py
 create mode 100644 app/main/views.py

diff --git a/app/factory.py b/app/factory.py
index a3e2da7..dab3607 100644
--- a/app/factory.py
+++ b/app/factory.py
@@ -17,6 +17,7 @@ from .extensions import (db, migrate, login_manager, ldap_manager, bootstrap,
                          admin, mail, jwt, toolbar, redis_store, fsession)
 from .admin.views import (AdminModelView, ItemAdmin, UserAdmin, GroupAdmin, TokenAdmin,
                           NetworkAdmin)
+from .main.views import bp as main
 from .inventory.views import bp as inventory
 from .networks.views import bp as networks
 from .users.views import bp as users
@@ -113,9 +114,10 @@ def create_app(config=None):
     admin.add_view(AdminModelView(models.Mac, db.session))
     admin.add_view(AdminModelView(models.Cname, db.session))
 
-    app.register_blueprint(inventory)
-    app.register_blueprint(networks)
-    app.register_blueprint(users)
+    app.register_blueprint(main)
+    app.register_blueprint(inventory, url_prefix='/inventory')
+    app.register_blueprint(networks, url_prefix='/networks')
+    app.register_blueprint(users, url_prefix='/users')
     app.register_blueprint(api, url_prefix='/api')
 
     app.wsgi_app = WhiteNoise(app.wsgi_app, root='static/')
diff --git a/app/inventory/views.py b/app/inventory/views.py
index 18f8b8b..c87bb69 100644
--- a/app/inventory/views.py
+++ b/app/inventory/views.py
@@ -21,24 +21,6 @@ from .. import utils, models
 bp = Blueprint('inventory', __name__)
 
 
-# Declare custom error handlers for all views
-@bp.app_errorhandler(404)
-def not_found_error(error):
-    return render_template('404.html'), 404
-
-
-@bp.app_errorhandler(500)
-def internal_error(error):
-    return render_template('500.html'), 500
-
-
-@bp.app_errorhandler(utils.CSEntryError)
-def handle_csentry_error(error):
-    response = jsonify(error.to_dict())
-    response.status_code = error.status_code
-    return response
-
-
 @bp.route('/_retrieve_items')
 @login_required
 def retrieve_items():
@@ -57,12 +39,6 @@ def retrieve_items():
     return jsonify(data=data)
 
 
-@bp.route('/')
-@login_required
-def index():
-    return render_template('index.html')
-
-
 @bp.route('/items')
 @login_required
 def list_items():
diff --git a/app/main/__init__.py b/app/main/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/app/main/views.py b/app/main/views.py
new file mode 100644
index 0000000..7cdb4d6
--- /dev/null
+++ b/app/main/views.py
@@ -0,0 +1,40 @@
+# -*- coding: utf-8 -*-
+"""
+app.main.views
+~~~~~~~~~~~~~~
+
+This module implements the main blueprint.
+
+:copyright: (c) 2017 European Spallation Source ERIC
+:license: BSD 2-Clause, see LICENSE for more details.
+
+"""
+from flask import Blueprint, render_template, jsonify
+from flask_login import login_required
+from .. import utils
+
+bp = Blueprint('main', __name__)
+
+
+# Declare custom error handlers for all views
+@bp.app_errorhandler(404)
+def not_found_error(error):
+    return render_template('404.html'), 404
+
+
+@bp.app_errorhandler(500)
+def internal_error(error):
+    return render_template('500.html'), 500
+
+
+@bp.app_errorhandler(utils.CSEntryError)
+def handle_csentry_error(error):
+    response = jsonify(error.to_dict())
+    response.status_code = error.status_code
+    return response
+
+
+@bp.route('/')
+@login_required
+def index():
+    return render_template('index.html')
diff --git a/app/static/js/attributes.js b/app/static/js/attributes.js
index 4d9be6e..d2aadc0 100644
--- a/app/static/js/attributes.js
+++ b/app/static/js/attributes.js
@@ -4,7 +4,7 @@ $(document).ready(function() {
     "ajax": function(data, callback, settings) {
       var kind = $('li a.nav-link.active').text();
       $.getJSON(
-        $SCRIPT_ROOT + "/_retrieve_attributes_name/" + kind,
+        $SCRIPT_ROOT + "/inventory/_retrieve_attributes_name/" + kind,
         function(json) {
           callback(json);
         });
diff --git a/app/static/js/hosts.js b/app/static/js/hosts.js
index 38c7e99..8b45519 100644
--- a/app/static/js/hosts.js
+++ b/app/static/js/hosts.js
@@ -5,7 +5,7 @@ $(document).ready(function() {
     // and update the IP select field
     var network_id = $("#network_id").val();
     $.getJSON(
-      $SCRIPT_ROOT + "/_retrieve_available_ips/" + network_id,
+      $SCRIPT_ROOT + "/networks/_retrieve_available_ips/" + network_id,
       function(json) {
         var $ip = $("#ip");
         $ip.empty();
@@ -27,7 +27,7 @@ $(document).ready(function() {
   var hosts_table =  $("#hosts_table").DataTable({
     "ajax": function(data, callback, settings) {
       $.getJSON(
-        $SCRIPT_ROOT + "/_retrieve_hosts",
+        $SCRIPT_ROOT + "/networks/_retrieve_hosts",
         function(json) {
           callback(json);
         });
diff --git a/app/static/js/items.js b/app/static/js/items.js
index 6c29a67..396f411 100644
--- a/app/static/js/items.js
+++ b/app/static/js/items.js
@@ -8,7 +8,7 @@ $(document).ready(function() {
   var items_table =  $("#items_table").DataTable({
     "ajax": function(data, callback, settings) {
       $.getJSON(
-        $SCRIPT_ROOT + "/_retrieve_items",
+        $SCRIPT_ROOT + "/inventory/_retrieve_items",
         function(json) {
           callback(json);
         });
@@ -30,7 +30,7 @@ $(document).ready(function() {
           if ( data === null ) {
             return data;
           }
-          var url = $SCRIPT_ROOT + "/items/view/" + data;
+          var url = $SCRIPT_ROOT + "/inventory/items/view/" + data;
           return '<a href="'+ url + '">' + data + '</a>';
         }
       }
diff --git a/app/templates/admin/index.html b/app/templates/admin/index.html
index 03782d6..996ac40 100644
--- a/app/templates/admin/index.html
+++ b/app/templates/admin/index.html
@@ -6,5 +6,5 @@
 <h2>Use the admin interface with care</h2>
 
 <!-- flask-admin uses bootstrap 3 -->
-<a class="btn btn-primary" href="{{ url_for('inventory.index') }}">CSEntry</a>
+<a class="btn btn-primary" href="{{ url_for('main.index') }}">CSEntry</a>
 {% endblock %}
diff --git a/app/templates/base.html b/app/templates/base.html
index 038fc7b..0f8c491 100644
--- a/app/templates/base.html
+++ b/app/templates/base.html
@@ -14,7 +14,7 @@
 {% block navbar %}
   <!-- Fixed navbar -->
   <div class="navbar fixed-top navbar-expand-lg navbar-light bg-light" role="navigation">
-      <a class="navbar-brand" href="{{ url_for('inventory.index') }}">CSEntry</a>
+      <a class="navbar-brand" href="{{ url_for('main.index') }}">CSEntry</a>
       <button class="navbar-toggler" type="button" data-toggle="collapse"
               data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent"
               aria-expanded="false" aria-label="Toggle navigation">
@@ -24,17 +24,17 @@
       <div class="collapse navbar-collapse" id="navbarSupportedContent">
         <div class="navbar-nav mr-auto">
           {% set path = request.path %}
-          <a class="nav-item nav-link {{ is_active(path.startswith("/items")) }}" href="{{ url_for('inventory.list_items') }}">Items</a>
-          <a class="nav-item nav-link {{ is_active(path.startswith("/hosts")) }}" href="{{ url_for('networks.list_hosts') }}">Hosts</a>
-          <a class="nav-item nav-link {{ is_active(path.startswith("/attributes")) }}" href="{{ url_for('inventory.attributes', kind='Manufacturer') }}">Attributes</a>
-          <a class="nav-item nav-link {{ is_active(path.startswith("/qrcodes")) }}" href="{{ url_for('inventory.qrcodes', kind='Action') }}">QR Codes</a>
+          <a class="nav-item nav-link {{ is_active(path.startswith("/inventory/items")) }}" href="{{ url_for('inventory.list_items') }}">Items</a>
+          <a class="nav-item nav-link {{ is_active(path.startswith("/networks/hosts")) }}" href="{{ url_for('networks.list_hosts') }}">Hosts</a>
+          <a class="nav-item nav-link {{ is_active(path.startswith("/inventory/attributes")) }}" href="{{ url_for('inventory.attributes', kind='Manufacturer') }}">Attributes</a>
+          <a class="nav-item nav-link {{ is_active(path.startswith("/inventory/qrcodes")) }}" href="{{ url_for('inventory.qrcodes', kind='Action') }}">QR Codes</a>
           {% if current_user.is_authenticated and current_user.is_admin %}
             <a class="nav-item nav-link" href="{{ url_for('admin.index') }}">Admin</a>
           {% endif %}
         </div>
         <div class="navbar-nav">
           {% if current_user.is_authenticated %}
-          <div class="dropdown {{ is_active(path == "/profile") }}">
+          <div class="dropdown {{ is_active(path == "/users/profile") }}">
             <a class="nav-link dropdown-toggle" href="#" id="navbarDropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
               {{current_user}}
             </a>
diff --git a/app/templates/users/profile.html b/app/templates/users/profile.html
index ad6e279..58f2ac6 100644
--- a/app/templates/users/profile.html
+++ b/app/templates/users/profile.html
@@ -47,7 +47,7 @@
       {% for token in user.tokens %}
       <tr>
         <td>
-          <form method="POST" action="/tokens/revoke">
+          <form method="POST" action="/users/tokens/revoke">
             <input id="token_id" name="token_id" type="hidden" value="{{ token.id }}">
             <input id="jti" name="jti" type="hidden" value="{{ token.jti }}">
             <button type="submit" class="btn btn-danger">
-- 
GitLab