From c3e0872637a3c3c23983959dad9d29b9cd43283f Mon Sep 17 00:00:00 2001
From: Benjamin Bertrand <benjamin.bertrand@esss.se>
Date: Tue, 17 Sep 2019 11:42:54 +0200
Subject: [PATCH] Add view network scope page

JIRA INFRA-1292 #action In Progress
---
 app/network/views.py                    |   7 +
 app/templates/_helpers.html             | 319 +++++++++++++-----------
 app/templates/network/networks.html     |  98 ++++----
 app/templates/network/scopes.html       |  82 +++---
 app/templates/network/view_network.html |   6 +-
 app/templates/network/view_scope.html   |  37 +++
 6 files changed, 307 insertions(+), 242 deletions(-)
 create mode 100644 app/templates/network/view_scope.html

diff --git a/app/network/views.py b/app/network/views.py
index 7b4895e..9648c05 100644
--- a/app/network/views.py
+++ b/app/network/views.py
@@ -553,6 +553,13 @@ def list_scopes():
     return render_template("network/scopes.html", scopes=scopes)
 
 
+@bp.route("/scopes/view/<name>")
+@login_required
+def view_scope(name):
+    scope = models.NetworkScope.query.filter_by(name=name).first_or_404()
+    return render_template("network/view_scope.html", scope=scope)
+
+
 @bp.route("/scopes/create", methods=("GET", "POST"))
 @login_groups_accepted("admin")
 def create_scope():
diff --git a/app/templates/_helpers.html b/app/templates/_helpers.html
index 1bf33fc..cf28011 100644
--- a/app/templates/_helpers.html
+++ b/app/templates/_helpers.html
@@ -16,15 +16,18 @@
 <div class="container flashed-messages">
   <div class="row">
     <div class="col-md-12">
-{% endif -%}
+      {% endif -%}
 
-{% for cat, msg in messages %}      <div class="alert alert-{{transform.get(cat.lower(), default_category or cat)}}{% if dismissible %} alert-dismissible{% endif %}" role="alert">
-{% if dismissible %}        <button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>{% endif %}
+      {% for cat, msg in messages %} <div
+        class="alert alert-{{transform.get(cat.lower(), default_category or cat)}}{% if dismissible %} alert-dismissible{% endif %}"
+        role="alert">
+        {% if dismissible %} <button type="button" class="close" data-dismiss="alert" aria-label="Close"><span
+            aria-hidden="true">&times;</span></button>{% endif %}
         {{msg}}
       </div>
-{%- endfor -%}
+      {%- endfor -%}
 
-{% if container %}
+      {% if container %}
     </div>
   </div>
 </div>
@@ -39,225 +42,239 @@
 {% if active %}active{% endif %}
 {%- endmacro %}
 
+{% macro link_to_scope(scope) -%}
+<a href="{{ url_for('network.view_scope', name=scope.name) }}">{{ scope.name }}</a>
+{%- endmacro %}
+
 {% macro link_to_network(network) -%}
-  <a href="{{ url_for('network.view_network', vlan_name=network.vlan_name) }}">{{ network.vlan_name }}</a>
+<a href="{{ url_for('network.view_network', vlan_name=network.vlan_name) }}">{{ network.vlan_name }}</a>
 {%- endmacro %}
 
 {% macro link_to_host(host) -%}
-  <a href="{{ url_for('network.view_host', name=host.name) }}">{{ host.fqdn|default(host.name) }}</a>
+<a href="{{ url_for('network.view_host', name=host.name) }}">{{ host.fqdn|default(host.name) }}</a>
+{%- endmacro %}
+
+{% macro link_to_networks(networks) -%}
+{% for network in networks %}
+{{ link_to_network(network) }}
+{% endfor %}
 {%- endmacro %}
 
 {% macro link_to_hosts(hosts) -%}
-  {% for host in hosts %}
-    {{ link_to_host(host) }}
-  {% endfor %}
+{% for host in hosts %}
+{{ link_to_host(host) }}
+{% endfor %}
 {%- endmacro %}
 
 {% macro link_to_interfaces_host(interfaces) -%}
-  {% for interface in interfaces %}
-    {{ link_to_host(interface.host) }}
-  {% endfor %}
+{% for interface in interfaces %}
+{{ link_to_host(interface.host) }}
+{% endfor %}
 {%- endmacro %}
 
 {% macro link_to_item(ics_id) -%}
-  {% if ics_id %}
-    <a href="{{ url_for('inventory.view_item', ics_id=ics_id) }}">{{ ics_id }}</a>
-  {% else %}
-    {{ ics_id }}
-  {% endif %}
+{% if ics_id %}
+<a href="{{ url_for('inventory.view_item', ics_id=ics_id) }}">{{ ics_id }}</a>
+{% else %}
+{{ ics_id }}
+{% endif %}
 {%- endmacro %}
 
 {% macro link_to_items(ics_ids) -%}
-  {% for ics_id in ics_ids %}
-    {{ link_to_item(ics_id) }}
-  {% endfor %}
+{% for ics_id in ics_ids %}
+{{ link_to_item(ics_id) }}
+{% endfor %}
 {%- endmacro %}
 
 {% macro link_to_stack_member(item) -%}
-  {% if item.stack_member is not none %}
-    <a href="{{ url_for('inventory.view_item', ics_id=item.ics_id) }}">{{ item.ics_id }} ({{ item.stack_member }})</a>
-  {% else %}
-    <a href="{{ url_for('inventory.view_item', ics_id=item.ics_id) }}">{{ item.ics_id }}</a>
-  {% endif %}
+{% if item.stack_member is not none %}
+<a href="{{ url_for('inventory.view_item', ics_id=item.ics_id) }}">{{ item.ics_id }} ({{ item.stack_member }})</a>
+{% else %}
+<a href="{{ url_for('inventory.view_item', ics_id=item.ics_id) }}">{{ item.ics_id }}</a>
+{% endif %}
 {%- endmacro %}
 
 {% macro link_to_stack_members(items) -%}
-  {% for item in items %}
-    {{ link_to_stack_member(item) }}
-  {% endfor %}
+{% for item in items %}
+{{ link_to_stack_member(item) }}
+{% endfor %}
 {%- endmacro %}
 
 {% macro link_to_ansible_group(group) -%}
-  <a href="{{ url_for('network.view_ansible_group', name=group.name) }}">{{ group.name }}</a>
+<a href="{{ url_for('network.view_ansible_group', name=group.name) }}">{{ group.name }}</a>
 {%- endmacro %}
 
 {% macro link_to_ansible_groups(groups) -%}
-  {% for group in groups %}
-    {{ link_to_ansible_group(group) }}
-  {% endfor %}
+{% for group in groups %}
+{{ link_to_ansible_group(group) }}
+{% endfor %}
 {%- endmacro %}
 
 {% macro link_to_task(task) -%}
-  <a href="{{ url_for('task.view_task', id_=task.id) }}">{{ task.id }}</a>
+<a href="{{ url_for('task.view_task', id_=task.id) }}">{{ task.id }}</a>
 {%- endmacro %}
 
 {% macro link_to_tasks(tasks) -%}
-  {% for task in tasks %}
-    {{ link_to_task(task) }}
-  {% endfor %}
+{% for task in tasks %}
+{{ link_to_task(task) }}
+{% endfor %}
 {%- endmacro %}
 
 {% macro render_field(field) -%}
-  {% set field_class = kwargs.pop('class_', '') + ' form-control' %}
-  {% set label_size = kwargs.pop('label_size', '2') %}
-  {% set input_size = kwargs.pop('input_size', '10') %}
+{% set field_class = kwargs.pop('class_', '') + ' form-control' %}
+{% set label_size = kwargs.pop('label_size', '2') %}
+{% set input_size = kwargs.pop('input_size', '10') %}
 
-  {% if field.errors %}
-    {% set field_class = field_class + ' is-invalid' %}
-  {% endif %}
+{% if field.errors %}
+{% set field_class = field_class + ' is-invalid' %}
+{% endif %}
 
-  <div class="form-group row">
-    {% if field.type == 'BooleanField' %}
-      <div class="col-sm-{{ input_size }} offset-sm-{{ label_size }}">
-        <div class="form-check">
-          {{ field(class_="form-check-input", **kwargs) }}
-          {{ field.label(class_="form-check-label") }}
-        </div>
-      </div>
-    {% else %}
-      {{ field.label(class_="col-sm-" + label_size + " col-form-label") }}
-      <div class="col-sm-{{ input_size }}">
-        {{ field(class_=field_class, **kwargs) }}
-        {% if field.description %}
-          <small class="form-text text-muted">
-            {{ field.description|safe }}
-          </small>
-        {% endif %}
-        {% if field.errors %}
-          <div class="invalid-feedback">
-            {{ field.errors|join(' / ') }}
-          </div>
-        {% endif %}
-      </div>
+<div class="form-group row">
+  {% if field.type == 'BooleanField' %}
+  <div class="col-sm-{{ input_size }} offset-sm-{{ label_size }}">
+    <div class="form-check">
+      {{ field(class_="form-check-input", **kwargs) }}
+      {{ field.label(class_="form-check-label") }}
+    </div>
+  </div>
+  {% else %}
+  {{ field.label(class_="col-sm-" + label_size + " col-form-label") }}
+  <div class="col-sm-{{ input_size }}">
+    {{ field(class_=field_class, **kwargs) }}
+    {% if field.description %}
+    <small class="form-text text-muted">
+      {{ field.description|safe }}
+    </small>
+    {% endif %}
+    {% if field.errors %}
+    <div class="invalid-feedback">
+      {{ field.errors|join(' / ') }}
+    </div>
     {% endif %}
   </div>
+  {% endif %}
+</div>
 {%- endmacro %}
 
 {% macro format_datetime(dt) -%}
-  {{ dt.strftime("%Y-%m-%d %H:%M") }}
+{{ dt.strftime("%Y-%m-%d %H:%M") }}
 {%- endmacro %}
 
 {% macro delete_button_with_confirmation(title, modal_id, message) -%}
-  <button type="button" class="btn btn-light" data-toggle="modal" data-target={{ "#%s" | format(modal_id) }}>
-    <span class="oi oi-trash" title="{{ title }}" aria-hidden="true"></span>
-  </button>
-  <!-- Modal -->
-  <div class="modal fade" id="{{ modal_id }}" tabindex="-1" role="dialog" aria-labelledby="delete-confirmation" aria-hidden="true">
-    <div class="modal-dialog" role="document">
-      <div class="modal-content">
-        <div class="modal-header">
-          <h6 class="modal-title">{{ message }}</h6>
-          <button type="button" class="close" data-dismiss="modal" aria-label="Close">
-            <span aria-hidden="true">&times;</span>
-          </button>
-        </div>
-        <div class="modal-footer">
-          <button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
-          <button type="submit" class="btn btn-primary">OK</button>
-        </div>
+<button type="button" class="btn btn-light" data-toggle="modal" data-target={{ "#%s" | format(modal_id) }}>
+  <span class="oi oi-trash" title="{{ title }}" aria-hidden="true"></span>
+</button>
+<!-- Modal -->
+<div class="modal fade" id="{{ modal_id }}" tabindex="-1" role="dialog" aria-labelledby="delete-confirmation"
+  aria-hidden="true">
+  <div class="modal-dialog" role="document">
+    <div class="modal-content">
+      <div class="modal-header">
+        <h6 class="modal-title">{{ message }}</h6>
+        <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+          <span aria-hidden="true">&times;</span>
+        </button>
+      </div>
+      <div class="modal-footer">
+        <button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
+        <button type="submit" class="btn btn-primary">OK</button>
       </div>
     </div>
   </div>
+</div>
 {%- endmacro %}
 
 {% macro submit_button_with_confirmation(title, message) -%}
-  <button type="button" class="btn btn-primary" data-toggle="modal" data-target="#submitModal" }}>
-    {{ title }}
-  </button>
-  <!-- Modal -->
-  <div class="modal fade" id="submitModal" tabindex="-1" role="dialog" aria-labelledby="submit-confirmation" aria-hidden="true">
-    <div class="modal-dialog" role="document">
-      <div class="modal-content">
-        <div class="modal-header">
-          <h6 class="modal-title">{{ message }}</h6>
-          <button type="button" class="close" data-dismiss="modal" aria-label="Close">
-            <span aria-hidden="true">&times;</span>
-          </button>
-        </div>
-        <div class="modal-footer">
-          <button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
-          <button type="submit" class="btn btn-primary">OK</button>
-        </div>
+<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#submitModal" }}>
+  {{ title }}
+</button>
+<!-- Modal -->
+<div class="modal fade" id="submitModal" tabindex="-1" role="dialog" aria-labelledby="submit-confirmation"
+  aria-hidden="true">
+  <div class="modal-dialog" role="document">
+    <div class="modal-content">
+      <div class="modal-header">
+        <h6 class="modal-title">{{ message }}</h6>
+        <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+          <span aria-hidden="true">&times;</span>
+        </button>
+      </div>
+      <div class="modal-footer">
+        <button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
+        <button type="submit" class="btn btn-primary">OK</button>
       </div>
     </div>
   </div>
+</div>
 {%- endmacro %}
 
 {% macro figure(filename, description) -%}
-  <figure class="figure">
-    <img src="{{ url_for('static', filename='img/' +  filename) }}" class="img-fluid mx-auto d-block" alt="{{ description }}">
-    <figcaption class="figure-caption text-center">{{ description }}</figcaption>
-  </figure>
+<figure class="figure">
+  <img src="{{ url_for('static', filename='img/' +  filename) }}" class="img-fluid mx-auto d-block"
+    alt="{{ description }}">
+  <figcaption class="figure-caption text-center">{{ description }}</figcaption>
+</figure>
 {%- endmacro %}
 
 {% macro waiting_for(title, label) -%}
-  <div class="modal" tabindex="-1" role="dialog" id="{{ label }}">
-    <div class="modal-dialog" role="document">
-      <div class="modal-content">
-        <div class="modal-header">
-          <h5 class="modal-title">{{ title }}</h5>
-        </div>
-        <div class="modal-body">
-          <div class="progress">
-            <div class="progress-bar progress-bar-striped progress-bar-animated" role="progressbar" style="width: 0%" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100">0%</div>
-          </div>
+<div class="modal" tabindex="-1" role="dialog" id="{{ label }}">
+  <div class="modal-dialog" role="document">
+    <div class="modal-content">
+      <div class="modal-header">
+        <h5 class="modal-title">{{ title }}</h5>
+      </div>
+      <div class="modal-body">
+        <div class="progress">
+          <div class="progress-bar progress-bar-striped progress-bar-animated" role="progressbar" style="width: 0%"
+            aria-valuenow="0" aria-valuemin="0" aria-valuemax="100">0%</div>
         </div>
       </div>
     </div>
   </div>
+</div>
 {%- endmacro %}
 
 {% macro item_comment_form(form, item) -%}
-  <form id="CommentForm" method="POST">
-    {{ form.hidden_tag() }}
-    <div class="form-group">
-      {{ form.body.label() }}
-      {{ form.body(class_="form-control", rows=5, required=True) }}
-      <small class="form-text text-muted">Styling with Markdown is supported using
-        <a href="https://github.com/showdownjs/showdown/wiki/Showdown's-Markdown-syntax" target="_blank">Showdown</a>.
-        A preview is visible below.
-      </small>
-    </div>
-    <div class="card">
-      <div class="card-header">
-        Comment preview
-      </div>
-      <div class="card-body" id="commentLivePreview"></div>
+<form id="CommentForm" method="POST">
+  {{ form.hidden_tag() }}
+  <div class="form-group">
+    {{ form.body.label() }}
+    {{ form.body(class_="form-control", rows=5, required=True) }}
+    <small class="form-text text-muted">Styling with Markdown is supported using
+      <a href="https://github.com/showdownjs/showdown/wiki/Showdown's-Markdown-syntax" target="_blank">Showdown</a>.
+      A preview is visible below.
+    </small>
+  </div>
+  <div class="card">
+    <div class="card-header">
+      Comment preview
     </div>
-    <br>
-    <button type="submit" class="btn btn-primary">Submit</button>
-    <a class="btn btn-danger" href="{{ url_for('inventory.view_item', ics_id=item.ics_id) }}">Cancel</a>
-  </form>
+    <div class="card-body" id="commentLivePreview"></div>
+  </div>
+  <br>
+  <button type="submit" class="btn btn-primary">Submit</button>
+  <a class="btn btn-danger" href="{{ url_for('inventory.view_item', ics_id=item.ics_id) }}">Cancel</a>
+</form>
 {%- endmacro %}
 
 {% macro item_comment(comment) -%}
-  <div class="card border-light mb-3">
-    <div class="card-header">
-      {{ comment.user }} commented on {{ format_datetime(comment.created_at) }}
-      {% if comment.updated_at != comment.created_at %}
-        <small class="">Edited {{ format_datetime(comment.updated_at) }}</small>
-      {% endif %}
-      <div class="float-sm-right">
-        <form method="POST" action="/inventory/items/comment/delete">
-          <input id="comment_id" name="comment_id" type="hidden" value="{{ comment.id }}">
-          {{ delete_button_with_confirmation("Delete comment", "deleteConfirmation-%s" | format(comment.id),
+<div class="card border-light mb-3">
+  <div class="card-header">
+    {{ comment.user }} commented on {{ format_datetime(comment.created_at) }}
+    {% if comment.updated_at != comment.created_at %}
+    <small class="">Edited {{ format_datetime(comment.updated_at) }}</small>
+    {% endif %}
+    <div class="float-sm-right">
+      <form method="POST" action="/inventory/items/comment/delete">
+        <input id="comment_id" name="comment_id" type="hidden" value="{{ comment.id }}">
+        {{ delete_button_with_confirmation("Delete comment", "deleteConfirmation-%s" | format(comment.id),
              "Are you sure you want to delete this comment?") }}
-        </form>
-      </div>
-      <a class="btn btn-light float-sm-right" href="{{ url_for('inventory.edit_comment', comment_id=comment.id) }}#body">
-        <span class="oi oi-pencil" title="Edit comment" aria-hidden="true"></span>
-      </a>
+      </form>
     </div>
-    <div class="card-body item-comment">{{ comment.body }}</div>
+    <a class="btn btn-light float-sm-right" href="{{ url_for('inventory.edit_comment', comment_id=comment.id) }}#body">
+      <span class="oi oi-pencil" title="Edit comment" aria-hidden="true"></span>
+    </a>
   </div>
-{%- endmacro %}
+  <div class="card-body item-comment">{{ comment.body }}</div>
+</div>
+{%- endmacro %}
\ No newline at end of file
diff --git a/app/templates/network/networks.html b/app/templates/network/networks.html
index 2b97346..a304b74 100644
--- a/app/templates/network/networks.html
+++ b/app/templates/network/networks.html
@@ -1,58 +1,60 @@
 {% extends "base-fluid.html" %}
-{% from "_helpers.html" import is_active, link_to_network %}
+{% from "_helpers.html" import is_active, link_to_network, link_to_scope %}
 
 {% block title %}Networks - CSEntry{% endblock %}
 
 {% block main %}
-  {% set path = request.path %}
-  <ul class="nav nav-tabs">
-    <li class="nav-item">
-      <a class="nav-link {{ is_active(path.endswith("/network/networks")) }}" href="{{ url_for('network.list_networks') }}">List networks</a>
-    </li>
-    <li class="nav-item">
-      <a class="nav-link {{ is_active(path.startswith("/network/networks/create")) }}" href="{{ url_for('network.create_network') }}">Register new network</a>
-    </li>
-    {% block networks_nav %}{% endblock %}
-  </ul>
+{% set path = request.path %}
+<ul class="nav nav-tabs">
+  <li class="nav-item">
+    <a class="nav-link {{ is_active(path.endswith("/network/networks")) }}"
+      href="{{ url_for('network.list_networks') }}">List networks</a>
+  </li>
+  <li class="nav-item">
+    <a class="nav-link {{ is_active(path.startswith("/network/networks/create")) }}"
+      href="{{ url_for('network.create_network') }}">Register new network</a>
+  </li>
+  {% block networks_nav %}{% endblock %}
+</ul>
 
-  <br>
+<br>
 
-  {% block networks_main %}
-  <table id="networks_table" class="table table-bordered table-hover table-sm" cellspacing="0" width="100%">
-    <thead>
-      <tr>
-        <th>Vlan name</th>
-        <th>Vlan id</th>
-        <th>Description</th>
-        <th>Address</th>
-        <th>First IP</th>
-        <th>Last IP</th>
-        <th>Gateway</th>
-        <th>Network scope</th>
-        <th>Domain</th>
-        <th>Admin only</th>
-      </tr>
-    </thead>
-    <tbody>
-      {% for network in networks %}
-        <tr>
-          <td>{{ link_to_network(network) }}</td>
-          <td>{{ network.vlan_id }}</td>
-          <td>{{ network.description | safe }}</td>
-          <td>{{ network.address }}</td>
-          <td>{{ network.first_ip }}</td>
-          <td>{{ network.last_ip }}</td>
-          <td>{{ network.gateway }}</td>
-          <td>{{ network.scope }}</td>
-          <td>{{ network.domain }}</td>
-          <td>{{ network.admin_only }}</td>
-        </tr>
-      {% endfor %}
-    </tbody>
-  </table>
-  {%- endblock %}
+{% block networks_main %}
+<table id="networks_table" class="table table-bordered table-hover table-sm" cellspacing="0" width="100%">
+  <thead>
+    <tr>
+      <th>Vlan name</th>
+      <th>Vlan id</th>
+      <th>Description</th>
+      <th>Address</th>
+      <th>First IP</th>
+      <th>Last IP</th>
+      <th>Gateway</th>
+      <th>Network scope</th>
+      <th>Domain</th>
+      <th>Admin only</th>
+    </tr>
+  </thead>
+  <tbody>
+    {% for network in networks %}
+    <tr>
+      <td>{{ link_to_network(network) }}</td>
+      <td>{{ network.vlan_id }}</td>
+      <td>{{ network.description | safe }}</td>
+      <td>{{ network.address }}</td>
+      <td>{{ network.first_ip }}</td>
+      <td>{{ network.last_ip }}</td>
+      <td>{{ network.gateway }}</td>
+      <td>{{ link_to_scope(network.scope) }}</td>
+      <td>{{ network.domain }}</td>
+      <td>{{ network.admin_only }}</td>
+    </tr>
+    {% endfor %}
+  </tbody>
+</table>
+{%- endblock %}
 {%- endblock %}
 
 {% block csentry_scripts %}
-  <script src="{{ url_for('static', filename='js/networks.js') }}"></script>
-{% endblock %}
+<script src="{{ url_for('static', filename='js/networks.js') }}"></script>
+{% endblock %}
\ No newline at end of file
diff --git a/app/templates/network/scopes.html b/app/templates/network/scopes.html
index 32a6b25..3b50bd1 100644
--- a/app/templates/network/scopes.html
+++ b/app/templates/network/scopes.html
@@ -1,50 +1,52 @@
 {% extends "base-fluid.html" %}
-{% from "_helpers.html" import is_active %}
+{% from "_helpers.html" import is_active, link_to_scope %}
 
 {% block title %}Network Scopes - CSEntry{% endblock %}
 
 {% block main %}
-  {% set path = request.path %}
-  <ul class="nav nav-tabs">
-    <li class="nav-item">
-      <a class="nav-link {{ is_active(path.endswith("/network/scopes")) }}" href="{{ url_for('network.list_scopes') }}">List network scopes</a>
-    </li>
-    <li class="nav-item">
-      <a class="nav-link {{ is_active(path.startswith("/network/scopes/create")) }}" href="{{ url_for('network.create_scope') }}">Register new network scope</a>
-    </li>
-    {% block scopes_nav %}{% endblock %}
-  </ul>
+{% set path = request.path %}
+<ul class="nav nav-tabs">
+  <li class="nav-item">
+    <a class="nav-link {{ is_active(path.endswith("/network/scopes")) }}"
+      href="{{ url_for('network.list_scopes') }}">List network scopes</a>
+  </li>
+  <li class="nav-item">
+    <a class="nav-link {{ is_active(path.startswith("/network/scopes/create")) }}"
+      href="{{ url_for('network.create_scope') }}">Register new network scope</a>
+  </li>
+  {% block scopes_nav %}{% endblock %}
+</ul>
 
-  <br>
+<br>
 
-  {% block scopes_main %}
-  <table id="scopes_table" class="table table-bordered table-hover table-sm" cellspacing="0" width="100%">
-    <thead>
-      <tr>
-        <th>Name</th>
-        <th>Description</th>
-        <th>First vlan</th>
-        <th>Last vlan</th>
-        <th>Supernet</th>
-        <th>Default domain</th>
-      </tr>
-    </thead>
-    <tbody>
-      {% for scope in scopes %}
-        <tr>
-          <td>{{ scope.name }}</td>
-          <td>{{ scope.description }}</td>
-          <td>{{ scope.first_vlan }}</td>
-          <td>{{ scope.last_vlan }}</td>
-          <td>{{ scope.supernet }}</td>
-          <td>{{ scope.domain }}</td>
-        </tr>
-      {% endfor %}
-    </tbody>
-  </table>
-  {%- endblock %}
+{% block scopes_main %}
+<table id="scopes_table" class="table table-bordered table-hover table-sm" cellspacing="0" width="100%">
+  <thead>
+    <tr>
+      <th>Name</th>
+      <th>Description</th>
+      <th>First vlan</th>
+      <th>Last vlan</th>
+      <th>Supernet</th>
+      <th>Default domain</th>
+    </tr>
+  </thead>
+  <tbody>
+    {% for scope in scopes %}
+    <tr>
+      <td>{{ link_to_scope(scope) }}</td>
+      <td>{{ scope.description }}</td>
+      <td>{{ scope.first_vlan }}</td>
+      <td>{{ scope.last_vlan }}</td>
+      <td>{{ scope.supernet }}</td>
+      <td>{{ scope.domain }}</td>
+    </tr>
+    {% endfor %}
+  </tbody>
+</table>
+{%- endblock %}
 {%- endblock %}
 
 {% block csentry_scripts %}
-  <script src="{{ url_for('static', filename='js/scopes.js') }}"></script>
-{% endblock %}
+<script src="{{ url_for('static', filename='js/scopes.js') }}"></script>
+{% endblock %}
\ No newline at end of file
diff --git a/app/templates/network/view_network.html b/app/templates/network/view_network.html
index 2170093..0cba1b6 100644
--- a/app/templates/network/view_network.html
+++ b/app/templates/network/view_network.html
@@ -1,7 +1,7 @@
 {% extends "network/networks.html" %}
-{% from "_helpers.html" import link_to_interfaces_host %}
+{% from "_helpers.html" import link_to_interfaces_host, link_to_scope %}
 
-{% block title %}View Ansible network - CSEntry{% endblock %}
+{% block title %}View Network - CSEntry{% endblock %}
 
 {% block networks_nav %}
 <li class="nav-item">
@@ -30,7 +30,7 @@
       <dt class="col-sm-3">Broadcast</dt>
       <dd class="col-sm-9">{{ network.broadcast }}</dd>
       <dt class="col-sm-3">Network Scope</dt>
-      <dd class="col-sm-9">{{ network.scope }}</dd>
+      <dd class="col-sm-9">{{ link_to_scope(network.scope) }}</dd>
       <dt class="col-sm-3">Domain</dt>
       <dd class="col-sm-9">{{ network.domain }}</dd>
       <dt class="col-sm-3">Admin only</dt>
diff --git a/app/templates/network/view_scope.html b/app/templates/network/view_scope.html
new file mode 100644
index 0000000..ceddbd7
--- /dev/null
+++ b/app/templates/network/view_scope.html
@@ -0,0 +1,37 @@
+{% extends "network/scopes.html" %}
+{% from "_helpers.html" import link_to_networks %}
+
+{% block title %}View Network Scope - CSEntry{% endblock %}
+
+{% block scopes_nav %}
+<li class="nav-item">
+  <a class="nav-link active" href="{{ url_for('network.view_scope', name=scope.name) }}">View network scope</a>
+</li>
+{% endblock %}
+
+{% block scopes_main %}
+<div class="row">
+  <div class="col-sm-9">
+    <dl class="row">
+      <dt class="col-sm-3">Name</dt>
+      <dd class="col-sm-9">{{ scope.name }}</dd>
+      <dt class="col-sm-3">First vlan</dt>
+      <dd class="col-sm-9">{{ scope.first_vlan }}</dd>
+      <dt class="col-sm-3">Last vlan</dt>
+      <dd class="col-sm-9">{{ scope.last_vlan }}</dd>
+      <dt class="col-sm-3">Description</dt>
+      <dd class="col-sm-9">{{ scope.description | safe }}</dd>
+      <dt class="col-sm-3">Supernet</dt>
+      <dd class="col-sm-9">{{ scope.supernet }}</dd>
+      <dt class="col-sm-3">Default domain</dt>
+      <dd class="col-sm-9">{{ scope.domain }}</dd>
+      <dt class="col-sm-3">Networks</dt>
+      <dd class="col-sm-9">{{ link_to_networks(scope.networks) }}</dd>
+      <dt class="col-sm-3">Created by</dt>
+      <dd class="col-sm-9">{{ scope.user }}</dd>
+      <dt class="col-sm-3">Created at</dt>
+      <dd class="col-sm-9">{{ scope.created_at }}</dd>
+    </dl>
+  </div>
+</div>
+{%- endblock %}
\ No newline at end of file
-- 
GitLab