Просмотр исходного кода

Template cleanup (#6421)

* Clean up & comment base templates

* Clean up login template & form

* Use SVG file for NetBox logo

* Simplify breadcrumbs

* Merge changelog.html into home.html

* Rename title_container block to header

* Move breadcrumbs block to object.html

* Attach names to endblock template tags

* Reorganize root-level templates into base/ and inc/

* Remove obsolete reference to Bootstrap 3.4.1
Jeremy Stretch 4 лет назад
Родитель
Сommit
805892f623
73 измененных файлов с 426 добавлено и 465 удалено
  1. 1 1
      netbox/templates/403.html
  2. 1 1
      netbox/templates/404.html
  3. 1 1
      netbox/templates/base/40x.html
  4. 33 13
      netbox/templates/base/base.html
  5. 128 0
      netbox/templates/base/layout.html
  6. 0 16
      netbox/templates/bottom.html
  7. 0 47
      netbox/templates/changelog.html
  8. 1 1
      netbox/templates/dcim/cable_connect.html
  9. 1 1
      netbox/templates/dcim/cable_trace.html
  10. 2 2
      netbox/templates/dcim/connections_list.html
  11. 1 1
      netbox/templates/dcim/device_component_add.html
  12. 1 1
      netbox/templates/dcim/devicebay_populate.html
  13. 1 1
      netbox/templates/dcim/devicetype_component_add.html
  14. 2 2
      netbox/templates/dcim/inc/devicetype_component_table.html
  15. 2 2
      netbox/templates/dcim/interface.html
  16. 1 1
      netbox/templates/dcim/rack_elevation_list.html
  17. 1 1
      netbox/templates/dcim/virtualchassis_add_member.html
  18. 1 1
      netbox/templates/dcim/virtualchassis_edit.html
  19. 1 1
      netbox/templates/exceptions/import_error.html
  20. 1 1
      netbox/templates/exceptions/permission_error.html
  21. 1 1
      netbox/templates/exceptions/programming_error.html
  22. 1 1
      netbox/templates/extras/object_changelog.html
  23. 1 1
      netbox/templates/extras/object_journal.html
  24. 12 16
      netbox/templates/extras/objectchange.html
  25. 5 9
      netbox/templates/extras/report.html
  26. 1 1
      netbox/templates/extras/report_list.html
  27. 5 10
      netbox/templates/extras/script.html
  28. 1 1
      netbox/templates/extras/script_list.html
  29. 1 1
      netbox/templates/extras/script_result.html
  30. 1 1
      netbox/templates/extras/tag.html
  31. 0 42
      netbox/templates/footer.html
  32. 17 17
      netbox/templates/generic/object.html
  33. 2 2
      netbox/templates/generic/object_bulk_add_component.html
  34. 2 2
      netbox/templates/generic/object_bulk_delete.html
  35. 2 2
      netbox/templates/generic/object_bulk_edit.html
  36. 2 2
      netbox/templates/generic/object_bulk_import.html
  37. 2 2
      netbox/templates/generic/object_bulk_remove.html
  38. 2 2
      netbox/templates/generic/object_bulk_rename.html
  39. 3 3
      netbox/templates/generic/object_delete.html
  40. 5 5
      netbox/templates/generic/object_edit.html
  41. 2 2
      netbox/templates/generic/object_import.html
  42. 4 4
      netbox/templates/generic/object_list.html
  43. 85 41
      netbox/templates/home.html
  44. 3 3
      netbox/templates/import_success.html
  45. 0 0
      netbox/templates/inc/messages.html
  46. 0 0
      netbox/templates/inc/panel_table.html
  47. 0 0
      netbox/templates/inc/profile_button.html
  48. 0 0
      netbox/templates/inc/responsive_table.html
  49. 1 1
      netbox/templates/ipam/aggregate.html
  50. 2 2
      netbox/templates/ipam/ipaddress.html
  51. 1 1
      netbox/templates/ipam/ipaddress_assign.html
  52. 2 2
      netbox/templates/ipam/prefix.html
  53. 1 1
      netbox/templates/ipam/prefix/ip_addresses.html
  54. 1 1
      netbox/templates/ipam/prefix/prefixes.html
  55. 2 2
      netbox/templates/ipam/routetarget.html
  56. 1 1
      netbox/templates/ipam/vlan.html
  57. 1 1
      netbox/templates/ipam/vlan/interfaces.html
  58. 1 1
      netbox/templates/ipam/vlan/vminterfaces.html
  59. 2 2
      netbox/templates/ipam/vrf.html
  60. 0 81
      netbox/templates/layout.html
  61. 58 52
      netbox/templates/login.html
  62. 0 18
      netbox/templates/logo.html
  63. 0 6
      netbox/templates/rest_framework/api.html
  64. 3 3
      netbox/templates/search.html
  65. 0 9
      netbox/templates/search_form.html
  66. 1 1
      netbox/templates/users/base.html
  67. 1 1
      netbox/templates/utilities/confirmation_form.html
  68. 2 2
      netbox/templates/utilities/obj_table.html
  69. 1 1
      netbox/templates/virtualization/cluster/devices.html
  70. 1 1
      netbox/templates/virtualization/cluster/virtual_machines.html
  71. 1 1
      netbox/templates/virtualization/virtualmachine_component_add.html
  72. 2 2
      netbox/templates/virtualization/vminterface.html
  73. 1 6
      netbox/users/forms.py

+ 1 - 1
netbox/templates/403.html

@@ -1,4 +1,4 @@
-{% extends '40x.html' %}
+{% extends 'base/40x.html' %}
 
 {% block title %}Access Denied{% endblock %}
 

+ 1 - 1
netbox/templates/404.html

@@ -1,4 +1,4 @@
-{% extends '40x.html' %}
+{% extends 'base/40x.html' %}
 
 {% block title %}Page Not Found{% endblock %}
 

+ 1 - 1
netbox/templates/40x.html → netbox/templates/base/40x.html

@@ -1,4 +1,4 @@
-{% extends 'layout.html' %}
+{% extends 'base/layout.html' %}
 
 {% block title %}{% endblock %}
 

+ 33 - 13
netbox/templates/base.html → netbox/templates/base/base.html

@@ -1,8 +1,20 @@
-{% load static %} {% load helpers %}
+{# Base template for (almost) all NetBox pages #}
+{% load static %}
+{% load static %}
+{% load helpers %}
 <!DOCTYPE html>
 <html lang="en">
   <head>
+    <meta charset="UTF-8" />
+    <meta
+      name="viewport"
+      content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width"
+    />
+
+    {# Page title #}
     <title>{% block title %}Home{% endblock %} | NetBox</title>
+
+    {# Static resources #}
     <link
       rel="stylesheet"
       href="{% static 'netbox-external.css'%}"
@@ -18,30 +30,38 @@
       href="{% static 'netbox-dark.css'%}"
       onerror="window.location='{% url 'media_failure' %}?filename=netbox-dark.css'"
     />
-
     <link rel="icon" type="image/png" href="{% static 'netbox.ico' %}" />
-    <meta charset="UTF-8" />
-    <meta
-      name="viewport"
-      content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width"
-    />
+
+    {# Javascript #}
     <script
       type="text/javascript"
       src="{% static 'netbox.js' %}"
       onerror="window.location='{% url 'media_failure' %}?filename=netbox.js'">
     </script>
+
+    {# Additional <head> content #}
     {% block head %}{% endblock %}
   </head>
-  {% with color_mode=preferences|get_key:'ui.colormode' %}
-  
-  <body{%if color_mode == 'dark'%} data-netbox-color-mode="dark"{% elif color_mode == 'light' %} data-netbox-color-mode="light"{% endif %}>
   
+  <body
+    {% if preferences|get_key:'ui.colormode' == 'dark'%} data-netbox-color-mode="dark"
+    {% else %} data-netbox-color-mode="light"
+    {% endif %}
+  >
+
+    {# Page layout #}
     {% block layout %}{% endblock %}
+
+    {# Additional Javascript #}
     {% block javascript %}{% endblock %}
-    {% include './messages.html' %}
+
+    {# User messages #}
+    {% include 'inc/messages.html' %}
+
+    {# Data container #}
     <div id="netbox-data" style="display: none!important; visibility: hidden!important">
-    {% block data %}{% endblock %}
+      {% block data %}{% endblock %}
     </div>
+
   </body>
-  {% endwith %}
 </html>

+ 128 - 0
netbox/templates/base/layout.html

@@ -0,0 +1,128 @@
+{# Base layout for the core NetBox UI w/navbar and page content #}
+{% extends 'base/base.html' %}
+{% load nav %}
+{% load search_options %}
+{% load static %}
+
+{% block layout %}
+  <div class="container-fluid">
+    <div class="row">
+      <main class="col-md-9 ms-sm-auto col-lg-10 px-0">
+
+        {# Sidebar #}
+        <nav id="sidebar-menu" class="col-md-3 col-lg-2 d-md-block sidebar collapse px-0">
+
+          {# Sidebar content #}
+          <div class="position-sticky pt-3">
+
+            {# Logo #}
+            <a class="px-2 sidebar-logo d-none d-md-flex" href="{% url 'home' %}">
+              <img src="{% static 'netbox_logo.svg' %}" alt="NetBox logo" />
+            </a>
+
+            {# Search bar #}
+            <ul class="nav flex-column">
+              <div class="d-block d-md-none mx-1 my-3 search-container">
+                {% search_options %}
+              </div>
+              <div class="d-flex d-md-none mx-1 my-3 justify-content-end">
+                {% include 'inc/profile_button.html' %}
+              </div>
+              {% nav %}
+            </ul>
+
+          </div>
+
+          {# Sidebar footer #}
+          <div class="d-flex flex-column container-fluid mt-auto justify-content-end sidebar-bottom">
+            <nav class="nav justify-content-between mb-2 mt-4 px-2">
+
+              {# Documentation #}
+              <a type="button" target="_blank" class="nav-link" href="https://netbox.readthedocs.io/">
+                <i title="Docs" class="mdi mdi-book-open-variant text-primary" data-bs-placement="top" data-bs-toggle="tooltip"></i>
+              </a>
+
+              {# API docs #}
+              <a class="nav-link" href="{% url 'api_docs' %}" target="_blank">
+                <i title="API" data-bs-placement="top" data-bs-toggle="tooltip" class="mdi mdi-code-braces text-primary"></i>
+              </a>
+
+              {# GitHub #}
+              <a class="nav-link" href="https://github.com/netbox-community/netbox" target="_blank">
+                <i title="Source Code" data-bs-placement="top" data-bs-toggle="tooltip" class="mdi mdi-code-tags text-primary"></i>
+              </a>
+
+              {# GitHub wiki #}
+              <a target="_blank" class="nav-link" href="https://github.com/netbox-community/netbox/wiki">
+                <i title="Get Help" data-bs-placement="top" data-bs-toggle="tooltip" class="mdi mdi-lifebuoy text-primary"></i>
+              </a>
+            </nav>
+          </div>
+
+        </nav>
+
+        {# Top bar #}
+        <nav class="navbar navbar-light sticky-top flex-md-nowrap py-4 search container-fluid">
+          <div class="d-md-none w-100 d-flex justify-content-between align-items-center my-3">
+              <a class="px-2 sidebar-logo d-block d-md-none" href="{% url 'home' %}">
+                <img src="{% static 'netbox_logo.svg' %}" alt="NetBox logo" />
+              </a>
+              <button
+                type="button"
+                aria-expanded="false"
+                data-bs-toggle="collapse"
+                aria-controls="sidebar-menu"
+                data-bs-target="#sidebar-menu"
+                aria-label="Toggle Navigation"
+                class="navbar-toggler position-relative collapsed"
+              >
+                <span class="navbar-toggler-icon"></span>
+              </button>
+            </div>
+            <div class="d-none d-md-flex w-100 search-container">
+              {% search_options %}
+              {% include 'inc/profile_button.html' %}
+            </div>
+        </nav>
+
+        {# Body #}
+        <div class="px-4 content-container">
+
+          {# Page header #}
+          {% block header %}
+            <div class="title-container">
+
+              {# Title #}
+              <div id="content-title">
+                <h1 class="h2 w-100">{% block title %}{% endblock %}</h1>
+              </div>
+
+              {# Controls #}
+              {% block controls %}{% endblock %}
+
+            </div>
+          {% endblock header %}
+
+          {# Page content #}
+          <div id="content" class="container-fluid p-0 m-0">
+            {% block tabs %}{% endblock %}
+            {% block content %}{% endblock %}
+          </div>
+
+          {# Page footer #}
+          <footer class="footer container-fluid pb-3 pt-4 px-0">
+            <div class="row align-items-center justify-content-end">
+            <div class="col-auto d-none d-md-block"></div>
+              <div class="col text-center text-md-end small text-muted">
+                <span class="fw-light d-block d-md-inline">{% now 'Y-m-d H:i:s T' %}</span>
+                <span class="ms-md-3 d-block d-md-inline">{{ settings.HOSTNAME }} (v{{ settings.VERSION }})</span>
+              </div>
+            </div>
+          </footer>
+
+        </div>
+
+      </main>
+    </div>
+  </div>
+{% endblock layout %}

+ 0 - 16
netbox/templates/bottom.html

@@ -1,16 +0,0 @@
-<div class="d-flex flex-column container-fluid mt-auto justify-content-end sidebar-bottom">
-  <nav class="nav justify-content-between mb-2 mt-4 px-2">
-    <a type="button" target="_blank" class="nav-link" href="https://netbox.readthedocs.io/">
-      <i title="Docs" class="mdi mdi-book-open-variant text-primary" data-bs-placement="top" data-bs-toggle="tooltip"></i>
-    </a>
-    <a class="nav-link" href="{% url 'api_docs' %}" target="_blank">
-      <i title="API" data-bs-placement="top" data-bs-toggle="tooltip" class="mdi mdi-code-braces text-primary"></i>
-    </a>
-    <a class="nav-link" href="https://github.com/netbox-community/netbox" target="_blank">
-      <i title="Source Code" data-bs-placement="top" data-bs-toggle="tooltip" class="mdi mdi-code-tags text-primary"></i>
-    </a>
-    <a target="_blank" class="nav-link" href="https://github.com/netbox-community/netbox/wiki">
-      <i title="Get Help" data-bs-placement="top" data-bs-toggle="tooltip" class="mdi mdi-lifebuoy text-primary"></i>
-    </a>
-  </nav>
-</div>

+ 0 - 47
netbox/templates/changelog.html

@@ -1,47 +0,0 @@
-{% load helpers %} {% load get_status %} 
-{% if changelog and perms.extras.view_objectchange %}
-<table class="table align-middle table-hover">
-  <thead>
-    <tr>
-      <th scope="col">User</th>
-      <th scope="col">Action</th>
-      <th scope="col">Type</th>
-      <th scope="col">Object</th>
-      <th scope="col">Time</th>
-      <th scope="col" align="right"></th>
-    </tr>
-  </thead>
-  <tbody>
-    {% for change in changelog %}
-    <tr class="{% get_status change.get_action_display %}">
-      <th scope="row">{{ change.user|default:change.user_name }}</th>
-      <td>{{ change.get_action_display|bettertitle }}</td>
-      <td>{{ change.changed_object_type.name|bettertitle }}</td>
-      <td>
-        {% if change.changed_object.get_absolute_url %}
-        <a class="text-body" href="{{ change.changed_object.get_absolute_url }}">{{ change.changed_object }}</a>
-        {% else %} {{ change.changed_object|default:change.object_repr }} {% endif %}
-      </td>
-      
-      <td>{{ change.time|date:'SHORT_DATETIME_FORMAT' }}</td>
-      <td>
-        <a role="button" class="text-body" href="{{ change.get_absolute_url }}">
-          <i class="mdi mdi-dots-horizontal" data-bs-toggle="tooltip" data-bs-placement="left" title="View Change Details"></i>
-        </a>
-      </td>
-    </tr>
-    {% endfor %}
-  </tbody>
-</table>
-
-{% elif perms.extras.view_objectchange %}
-<div class="alert alert-secondary mt-4" role="alert">
-  No change history found.
-</div>
-
-{% else %}
-<div class="alert alert-danger mt-4" role="alert">
-  <strong>{{ request.user|truncatechars:"30" }}</strong> does not have
-  permission to view changes.
-</div>
-{% endif %}

+ 1 - 1
netbox/templates/dcim/cable_connect.html

@@ -1,4 +1,4 @@
-{% extends 'layout.html' %}
+{% extends 'base/layout.html' %}
 {% load static %}
 {% load helpers %}
 {% load form_helpers %}

+ 1 - 1
netbox/templates/dcim/cable_trace.html

@@ -1,4 +1,4 @@
-{% extends 'layout.html' %}
+{% extends 'base/layout.html' %}
 {% load helpers %}
 
 {% block header %}

+ 2 - 2
netbox/templates/dcim/connections_list.html

@@ -1,4 +1,4 @@
-{% extends 'layout.html' %}
+{% extends 'base/layout.html' %}
 {% load buttons %}
 
 {% block title %}{{ title }}{% endblock %}
@@ -10,7 +10,7 @@
     <div class="col col-md-9">
         <div class="card">
             <div class="card-body">
-                {% include 'responsive_table.html' %}
+                {% include 'inc/responsive_table.html' %}
             </div>
         </div>
         {% include 'inc/paginator.html' with paginator=table.paginator page=table.page %}

+ 1 - 1
netbox/templates/dcim/device_component_add.html

@@ -1,4 +1,4 @@
-{% extends 'layout.html' %}
+{% extends 'base/layout.html' %}
 {% load form_helpers %}
 
 {% block title %}Create {{ component_type }}{% endblock %}

+ 1 - 1
netbox/templates/dcim/devicebay_populate.html

@@ -1,4 +1,4 @@
-{% extends 'layout.html' %}
+{% extends 'base/layout.html' %}
 {% load form_helpers %}
 
 {% render_errors form %}

+ 1 - 1
netbox/templates/dcim/devicetype_component_add.html

@@ -1,4 +1,4 @@
-{% extends 'layout.html' %}
+{% extends 'base/layout.html' %}
 {% load form_helpers %}
 
 {% block title %}Add {{ component_type }} to {{ parent }}{% endblock %}

+ 2 - 2
netbox/templates/dcim/inc/devicetype_component_table.html

@@ -7,7 +7,7 @@
                 {{ title }}
             </h5>
             <div class="card-body">
-                {% include 'responsive_table.html' %}
+                {% include 'inc/responsive_table.html' %}
             </div>
             <div class="card-footer noprint">
                 {% if table.rows %}
@@ -37,7 +37,7 @@
             {{ title }}
         </h5>
         <div class="card-body">
-            {% include 'responsive_table.html' %}
+            {% include 'inc/responsive_table.html' %}
         </div>
     </div>
 {% endif %}

+ 2 - 2
netbox/templates/dcim/interface.html

@@ -291,12 +291,12 @@
     </div>
     <div class="row mb-3">
         <div class="col col-md-12">
-            {% include 'panel_table.html' with table=vlan_table heading="VLANs" %}
+            {% include 'inc/panel_table.html' with table=vlan_table heading="VLANs" %}
         </div>
     </div>
     <div class="row mb-3">
         <div class="col col-md-12">
-            {% include 'panel_table.html' with table=child_interfaces_table heading="Child Interfaces" %}
+            {% include 'inc/panel_table.html' with table=child_interfaces_table heading="Child Interfaces" %}
         </div>
     </div>
     <div class="row mb-3">

+ 1 - 1
netbox/templates/dcim/rack_elevation_list.html

@@ -1,4 +1,4 @@
-{% extends 'layout.html' %}
+{% extends 'base/layout.html' %}
 {% load helpers %}
 {% load static %}
 

+ 1 - 1
netbox/templates/dcim/virtualchassis_add_member.html

@@ -1,4 +1,4 @@
-{% extends 'layout.html' %}
+{% extends 'base/layout.html' %}
 {% load form_helpers %}
 
 {% block title %}Add New Member to Virtual Chassis {{ virtual_chassis }}{% endblock %}

+ 1 - 1
netbox/templates/dcim/virtualchassis_edit.html

@@ -1,4 +1,4 @@
-{% extends 'layout.html' %}
+{% extends 'base/layout.html' %}
 {% load helpers %}
 {% load form_helpers %}
 

+ 1 - 1
netbox/templates/exceptions/import_error.html

@@ -16,4 +16,4 @@
         has recently been upgraded, check that the WSGI service (e.g. gunicorn or uWSGI) has been restarted. This
         ensures that the new code is running.
     </p>
-{% endblock %}
+{% endblock message %}

+ 1 - 1
netbox/templates/exceptions/permission_error.html

@@ -9,4 +9,4 @@
         media root is <code>{{ settings.MEDIA_ROOT }}</code>. Ensure that the user NetBox runs as has access to write
         files to all locations within this path.
     </p>
-{% endblock %}
+{% endblock message %}

+ 1 - 1
netbox/templates/exceptions/programming_error.html

@@ -14,4 +14,4 @@
         can check this by connecting to the database using NetBox's credentials and issuing a query for
         <code>SELECT VERSION()</code>.
     </p>
-{% endblock %}
+{% endblock message %}

+ 1 - 1
netbox/templates/extras/object_changelog.html

@@ -3,7 +3,7 @@
 {% block title %}{{ object }} - Change Log{% endblock %}
 
 {% block content %}
-    {% include 'panel_table.html' %}
+    {% include 'inc/panel_table.html' %}
     {% include 'inc/paginator.html' with paginator=table.paginator page=table.page %}
     <div class="text-muted">
         Change log retention: {% if settings.CHANGELOG_RETENTION %}{{ settings.CHANGELOG_RETENTION }} days{% else %}Indefinite{% endif %}

+ 1 - 1
netbox/templates/extras/object_journal.html

@@ -26,7 +26,7 @@
     </form>
     {% endif %}
     <div class="col col-md-9 mb-3">
-        {% include 'panel_table.html' %}
+        {% include 'inc/panel_table.html' %}
     </div>
     {% include 'inc/paginator.html' with paginator=table.paginator page=table.page %}
 {% endblock %}

+ 12 - 16
netbox/templates/extras/objectchange.html

@@ -1,22 +1,18 @@
-{% extends 'layout.html' %}
+{% extends 'base/layout.html' %}
 {% load helpers %}
 
 {% block title %}{{ object }}{% endblock %}
 
-{% block breadcrumb_main %}
-<nav class="breadcrumb-container" aria-label="breadcrumb">
-    <ol class="breadcrumb">
-        <li class="breadcrumb-item"><a href="{% url 'extras:objectchange_list' %}">Change Log</a></li>
-        {% if object.related_object.get_absolute_url %}
-            <li class="breadcrumb-item"><a href="{{ object.related_object.get_absolute_url }}changelog/">{{ object.related_object }}</a></li>
-        {% elif object.changed_object.get_absolute_url %}
-            <li class="breadcrumb-item"><a href="{{ object.changed_object.get_absolute_url }}changelog/">{{ object.changed_object }}</a></li>
-        {% elif object.changed_object %}
-            <li class="breadcrumb-item">{{ object.changed_object }}</li>
-        {% endif %}
-        <li class="breadcrumb-item">{{ object }}</li>
-    </ol>
-</nav>
+{% block breadcrumbs %}
+  <li class="breadcrumb-item"><a href="{% url 'extras:objectchange_list' %}">Change Log</a></li>
+  {% if object.related_object.get_absolute_url %}
+    <li class="breadcrumb-item"><a href="{{ object.related_object.get_absolute_url }}changelog/">{{ object.related_object }}</a></li>
+  {% elif object.changed_object.get_absolute_url %}
+    <li class="breadcrumb-item"><a href="{{ object.changed_object.get_absolute_url }}changelog/">{{ object.changed_object }}</a></li>
+  {% elif object.changed_object %}
+    <li class="breadcrumb-item">{{ object.changed_object }}</li>
+  {% endif %}
+  <li class="breadcrumb-item">{{ object }}</li>
 {% endblock %}
 
 {% block header %}
@@ -159,7 +155,7 @@
 </div>
 <div class="row mb-3">
     <div class="col col-md-12">
-        {% include 'panel_table.html' with table=related_changes_table heading='Related Changes' panel_class='default' %}
+        {% include 'inc/panel_table.html' with table=related_changes_table heading='Related Changes' panel_class='default' %}
         {% if related_changes_count > related_changes_table.rows|length %}
             <div class="float-end">
                 <a href="{% url 'extras:objectchange_list' %}?request_id={{ object.request_id }}" class="btn btn-primary">See All {{ related_changes_count|add:"1" }} Changes</a>

+ 5 - 9
netbox/templates/extras/report.html

@@ -1,16 +1,12 @@
-{% extends 'layout.html' %}
+{% extends 'base/layout.html' %}
 {% load helpers %}
 
 {% block title %}{{ report.name }}{% endblock %}
 
-{% block breadcrumb_main %}
-<nav class="breadcrumb-container" aria-label="breadcrumb">
-    <ol class="breadcrumb">
-        <li class="breadcrumb-item"><a href="{% url 'extras:report_list' %}">Reports</a></li>
-        <li class="breadcrumb-item"><a href="{% url 'extras:report_list' %}#module.{{ report.module }}">{{ report.module|bettertitle }}</a></li>
-        <li class="breadcrumb-item">{{ report.name }}</li>
-    </ol>
-</nav>
+{% block breadcrumbs %}
+  <li class="breadcrumb-item"><a href="{% url 'extras:report_list' %}">Reports</a></li>
+  <li class="breadcrumb-item"><a href="{% url 'extras:report_list' %}#module.{{ report.module }}">{{ report.module|bettertitle }}</a></li>
+  <li class="breadcrumb-item">{{ report.name }}</li>
 {% endblock %}
 
 {% block content %}

+ 1 - 1
netbox/templates/extras/report_list.html

@@ -1,4 +1,4 @@
-{% extends 'layout.html' %}
+{% extends 'base/layout.html' %}
 {% load helpers %}
 
 {% block title %}Reports{% endblock %}

+ 5 - 10
netbox/templates/extras/script.html

@@ -1,19 +1,14 @@
-{% extends 'layout.html' %}
+{% extends 'base/layout.html' %}
 {% load helpers %}
 {% load form_helpers %}
 {% load log_levels %}
 
 {% block title %}{{ script }}{% endblock %}
 
-{% block breadcrumb_main %}
-<nav class="breadcrumb-container" aria-label="breadcrumb">
-    <ol class="breadcrumb">
-        <li class="breadcrumb-item"><a href="/">Home</a></li>
-        <li class="breadcrumb-item"><a href="{% url 'extras:script_list' %}">Scripts</a></li>
-        <li class="breadcrumb-item"><a href="{% url 'extras:script_list' %}#module.{{ module }}">{{ module|bettertitle }}</a></li>
-        <li class="breadcrumb-item">{{ script }}</li>
-    </ol>
-</nav>
+{% block breadcrumbs %}
+  <li class="breadcrumb-item"><a href="{% url 'extras:script_list' %}">Scripts</a></li>
+  <li class="breadcrumb-item"><a href="{% url 'extras:script_list' %}#module.{{ module }}">{{ module|bettertitle }}</a></li>
+  <li class="breadcrumb-item">{{ script }}</li>
 {% endblock %}
 
 {% block content %}

+ 1 - 1
netbox/templates/extras/script_list.html

@@ -1,4 +1,4 @@
-{% extends 'layout.html' %}
+{% extends 'base/layout.html' %}
 {% load helpers %}
 
 {% block title %}Scripts{% endblock %}

+ 1 - 1
netbox/templates/extras/script_result.html

@@ -1,4 +1,4 @@
-{% extends 'layout.html' %}
+{% extends 'base/layout.html' %}
 {% load helpers %}
 {% load form_helpers %}
 {% load log_levels %}

+ 1 - 1
netbox/templates/extras/tag.html

@@ -51,7 +51,7 @@
     </div>
   </div>
   <div class="col col-md-6">
-    {% include 'panel_table.html' with table=items_table heading='Tagged Objects' %}
+    {% include 'inc/panel_table.html' with table=items_table heading='Tagged Objects' %}
     {% include 'inc/paginator.html' with paginator=items_table.paginator page=items_table.page %}
   </div>
 </div>

+ 0 - 42
netbox/templates/footer.html

@@ -1,42 +0,0 @@
-<footer class="footer mt-auto bg-light p-3 text-center">
-  <div class="container-fluid">
-    <div class="row">
-      <div class="col d-flex flex-column justify-content-center">
-        <span class="text-muted">
-          {{ settings.HOSTNAME }} (v{{ settings.VERSION }})
-        </span>
-      </div>
-      <div class="col d-flex flex-column justify-content-center">
-        <span class="text-muted">{% now 'Y-m-d H:i:s T' %}</span>
-      </div>
-      <div class="col d-flex flex-column justify-content-center">
-        <nav class="nav">
-          <a
-            class="nav-link"
-            href="https://netbox.readthedocs.io/"
-            target="_blank"
-          >
-            <i class="mdi mdi-book-open-page-variant text-primary"></i> Docs
-          </a>
-          <a class="nav-link" href="{% url 'api_docs' %}" target="_blank">
-            <i class="mdi mdi-cloud-braces text-primary"></i> API
-          </a>
-          <a
-            class="nav-link"
-            href="https://github.com/netbox-community/netbox"
-            target="_blank"
-          >
-            <i class="mdi mdi-xml text-primary"></i> Code
-          </a>
-          <a
-            class="nav-link"
-            href="https://github.com/netbox-community/netbox/wiki"
-            target="_blank"
-          >
-            <i class="mdi mdi-lifebuoy text-primary"></i> Help
-          </a>
-        </nav>
-      </div>
-    </div>
-  </div>
-</footer>

+ 17 - 17
netbox/templates/generic/object.html

@@ -1,22 +1,22 @@
-{% extends 'layout.html' %}
+{% extends 'base/layout.html' %}
 {% load buttons %}
 {% load custom_links %}
 {% load helpers %}
 {% load perms %}
 {% load plugins %}
 
+{% block header %}
+  {# Breadcrumbs #}
+  <nav class="breadcrumb-container" aria-label="breadcrumb">
+    <ol class="breadcrumb">
+      {% block breadcrumbs %}{% endblock %}
+    </ol>
+  </nav>
+  {{ block.super }}
+{% endblock %}
 
 {% block title %}{{ object }}{% endblock %}
 
-{% block breadcrumb_main %}
-<nav class="breadcrumb-container" aria-label="breadcrumb">
-  <ol class="breadcrumb">
-    <li class="breadcrumb-item"><a href="/">Home</a></li>
-    {% block breadcrumbs %}{%endblock%}
-  </ol>
-</nav>
-{% endblock %}
-
 {% block controls %}
 <div class="controls mb-2 mx-0">
   <div class="d-flex flex-wrap justify-content-end">
@@ -34,15 +34,15 @@
   {% endif %}
   </div>
 </div>
-{% endblock %}
+{% endblock controls %}
 
 {% block tabs %}
 <ul class="nav nav-tabs mb-3">
   {% block tab_items %}
-  <li class="nav-item" role="presentation">
-    <a class="nav-link{% if not active_tab %} active{% endif %}" href="{{ object.get_absolute_url }}">{{ object|meta:"verbose_name"|bettertitle }}</a>
-  </li>
-  {% endblock %}
+    <li class="nav-item" role="presentation">
+      <a class="nav-link{% if not active_tab %} active{% endif %}" href="{{ object.get_absolute_url }}">{{ object|meta:"verbose_name"|bettertitle }}</a>
+    </li>
+  {% endblock tab_items %}
   {% if perms.extras.view_journalentry %}
     {% with journal_viewname=object|viewname:'journal' %}
     {% url journal_viewname pk=object.pk as journal_url %}
@@ -62,7 +62,7 @@
     {% endwith %}
   {% endif %}
 </ul>
-{% endblock %}
+{% endblock tabs %}
 
 {% block content %}
 <p>
@@ -72,5 +72,5 @@
   </small>
   <span class="badge bg-primary">{{ object|meta:"app_label" }}.{{ object|meta:"model_name" }}:{{ object.pk }}</span>
 </p>
-{% endblock %}
+{% endblock content %}
 {% block components %}{% endblock %}

+ 2 - 2
netbox/templates/generic/object_bulk_add_component.html

@@ -1,4 +1,4 @@
-{% extends 'layout.html' %}
+{% extends 'base/layout.html' %}
 {% load form_helpers %}
 
 {% block title %}Add {{ model_name|title }}{% endblock %}
@@ -37,4 +37,4 @@
         </div>
     </div>
 </form>
-{% endblock %}
+{% endblock content %}

+ 2 - 2
netbox/templates/generic/object_bulk_delete.html

@@ -1,4 +1,4 @@
-{% extends 'layout.html' %}
+{% extends 'base/layout.html' %}
 {% load helpers %}
 
 {% block title %}Delete {{ table.rows|length }} {{ obj_type_plural|bettertitle }}?{% endblock %}
@@ -39,4 +39,4 @@
             </form>
         </div>
     </div>
-{% endblock %}
+{% endblock content %}

+ 2 - 2
netbox/templates/generic/object_bulk_edit.html

@@ -1,4 +1,4 @@
-{% extends 'layout.html' %}
+{% extends 'base/layout.html' %}
 {% load helpers %}
 {% load form_helpers %}
 
@@ -42,4 +42,4 @@
         </div>
     </div>
 </form>
-{% endblock %}
+{% endblock content %}

+ 2 - 2
netbox/templates/generic/object_bulk_import.html

@@ -1,4 +1,4 @@
-{% extends 'layout.html' %}
+{% extends 'base/layout.html' %}
 {% load helpers %}
 {% load form_helpers %}
 
@@ -127,4 +127,4 @@
             </div>
         </div>
     </div>
-{% endblock %}
+{% endblock content %}

+ 2 - 2
netbox/templates/generic/object_bulk_remove.html

@@ -1,4 +1,4 @@
-{% extends 'layout.html' %}
+{% extends 'base/layout.html' %}
 {% load helpers %}
 
 {% block title %}Remove {{ table.rows|length }} {{ obj_type_plural|bettertitle }}?{% endblock %}
@@ -37,4 +37,4 @@
         </form>
     </div>
 </div>
-{% endblock %}
+{% endblock content %}

+ 2 - 2
netbox/templates/generic/object_bulk_rename.html

@@ -1,4 +1,4 @@
-{% extends 'layout.html' %}
+{% extends 'base/layout.html' %}
 {% load helpers %}
 {% load form_helpers %}
 
@@ -47,4 +47,4 @@
         </form>
     </div>
 </div>
-{% endblock %}
+{% endblock content %}

+ 3 - 3
netbox/templates/generic/object_delete.html

@@ -4,6 +4,6 @@
 {% block title %}Delete {{ obj_type }}?{% endblock %}
 
 {% block message %}
-    <p>Are you sure you want to delete {{ obj_type }} <strong>{{ obj }}</strong>?</p>
-    {% block message_extra %}{% endblock %}
-{% endblock %}
+  <p>Are you sure you want to delete {{ obj_type }} <strong>{{ obj }}</strong>?</p>
+  {% block message_extra %}{% endblock %}
+{% endblock message %}

+ 5 - 5
netbox/templates/generic/object_edit.html

@@ -1,4 +1,4 @@
-{% extends 'layout.html' %} {% load form_helpers %} {% load helpers %} 
+{% extends 'base/layout.html' %} {% load form_helpers %} {% load helpers %}
 
 {% block title %}{% if obj.pk %}Editing {{ obj_type }} {{ obj }}{% else %}Add a new {{ obj_type }}{% endif %}{% endblock %}
 
@@ -8,7 +8,7 @@
     <i class="mdi mdi-help-circle"></i>
   </button>
   {% endif %}
-{% endblock %}
+{% endblock controls %}
 
 {% block content %}
 <form action="" method="post" enctype="multipart/form-data">
@@ -47,7 +47,7 @@
         {% block form_fields %}{% render_form form %}{% endblock %}
       </div>
       {% endif %}
-      {% endblock %}
+      {% endblock form %}
     </div>
   </div>
   <div class="row my-3">
@@ -66,11 +66,11 @@
         Create
       </button>
       {% endif %}
-      {% endblock %}
+      {% endblock buttons %}
     </div>
   </div>
 </form>
 {% if obj and settings.DOCS_ROOT %} 
   {% include 'inc/modal.html' with name='docs' content=obj|get_docs %}
 {% endif %}
-{% endblock %}
+{% endblock content %}

+ 2 - 2
netbox/templates/generic/object_import.html

@@ -1,4 +1,4 @@
-{% extends 'layout.html' %}
+{% extends 'base/layout.html' %}
 {% load helpers %}
 {% load form_helpers %}
 
@@ -22,4 +22,4 @@
 		</form>
 	</div>
 </div>
-{% endblock %}
+{% endblock content %}

+ 4 - 4
netbox/templates/generic/object_list.html

@@ -1,4 +1,4 @@
-{% extends 'layout.html' %}
+{% extends 'base/layout.html' %}
 {% load buttons %}
 {% load helpers %}
 {% load render_table from django_tables2 %}
@@ -21,7 +21,7 @@
     {% endif %}
   </div>
 </div>
-{% endblock %}
+{% endblock controls %}
 
 {% block content %}
 {% if table.paginator.num_pages > 1 %}
@@ -78,7 +78,7 @@
                 <form method="post" class="form form-horizontal">
                     {% csrf_token %}
                     <input type="hidden" name="return_url" value="{% if return_url %}{{ return_url }}{% else %}{{ request.path }}{% if request.GET %}?{{ request.GET.urlencode }}{% endif %}{% endif %}" />
-                    {% include table_template|default:'responsive_table.html' %}
+                    {% include table_template|default:'inc/responsive_table.html' %}
                     <div class="float-start noprint bulk-buttons">
                         {% block bulk_buttons %}{% endblock %}
                         {% if bulk_edit_url and permissions.change %}
@@ -111,4 +111,4 @@
     {% endif %}
 </div>
 {% table_config_form table table_name="ObjectTable" %}
-{% endblock %}
+{% endblock content %}

+ 85 - 41
netbox/templates/home.html

@@ -1,56 +1,100 @@
-{% extends 'layout.html' %}
+{% extends 'base/layout.html' %}
+{% load get_status %}
 {% load helpers %}
 
-{% block title_container %}{% endblock %}
+{% block header %}{% endblock %}
 {% block title %}Home{% endblock %}
 
 {% block content %}
-<div class="stats-container">
-  <div class="row masonry">
-    {% for section in stats %}
-    <div class="col col-sm-12 col-md-4 my-2 masonry-item">
-      <div class="card">
-        <h5 class="card-header text-primary">{{ section.label }}</h5>
-        <div class="card-body">
-          <div class="list-group list-group-flush">
-            {% for item in section.items %}
-            <a href="{% url item.url %}" class="list-group-item list-group-item-action{% if item.disabled %} disabled{% endif %}">
-              <div class="d-flex w-100 justify-content-between align-items-center">
-                <div class="d-flex flex-column align-items-start">
-                  <h6 class="mb-1">{{ item.label }}</h6>
-                  {% if item.description %}
-                  <small class="mb-1 text-muted">{{ item.description }}</small>
-                  {% endif %}
+
+  {# General stats #}
+  <div class="stats-container">
+    <div class="row masonry">
+      {% for section in stats %}
+      <div class="col col-sm-12 col-md-4 my-2 masonry-item">
+        <div class="card">
+          <h5 class="card-header text-primary">{{ section.label }}</h5>
+          <div class="card-body">
+            <div class="list-group list-group-flush">
+              {% for item in section.items %}
+              <a href="{% url item.url %}" class="list-group-item list-group-item-action{% if item.disabled %} disabled{% endif %}">
+                <div class="d-flex w-100 justify-content-between align-items-center">
+                  <div class="d-flex flex-column align-items-start">
+                    <h6 class="mb-1">{{ item.label }}</h6>
+                    {% if item.description %}
+                    <small class="mb-1 text-muted">{{ item.description }}</small>
+                    {% endif %}
+                  </div>
+                  <span class="badge stat-badge rounded-pill">
+                    {% if item.count == None %}
+                      <i class="mdi mdi-lock"></i>
+                    {% else %}
+                      {{ item.count }}
+                    {% endif %}
+                  </span>
                 </div>
-                <span class="badge stat-badge rounded-pill">
-                  {% if item.count == None %}
-                    <i class="mdi mdi-lock"></i>
-                  {% else %}
-                    {{ item.count }}
-                  {% endif %}
-                </span>
-              </div>
-            </a>
-            {% endfor %}
-          </div>
-          <div class="display-4 font-weight-normal text-primary">
-            {{ item.count }}
+              </a>
+              {% endfor %}
+            </div>
+            <div class="display-4 font-weight-normal text-primary">
+              {{ item.count }}
+            </div>
           </div>
         </div>
       </div>
+      {% endfor %}
     </div>
-    {% endfor %}
   </div>
-</div>
 
-<div class="row my-4 flex-grow-1 changelog-container">
-  <div class="col">
-    <div class="card">
-      <h4 class="card-header">Changelog</h4>
-      <div class="card-body">
-        {% include 'changelog.html' %}
+  {# Changelog #}
+  <div class="row my-4 flex-grow-1 changelog-container">
+    <div class="col">
+      <div class="card">
+        <h4 class="card-header">Changelog</h4>
+        <div class="card-body">
+          {% if changelog and perms.extras.view_objectchange %}
+            {# TODO: Replace this with a django-tables2 Table #}
+            <table class="table align-middle table-hover">
+              <thead>
+                <tr>
+                  <th scope="col">User</th>
+                  <th scope="col">Action</th>
+                  <th scope="col">Type</th>
+                  <th scope="col">Object</th>
+                  <th scope="col">Time</th>
+                  <th scope="col" align="right"></th>
+                </tr>
+              </thead>
+              <tbody>
+                {% for change in changelog %}
+                  <tr class="{% get_status change.get_action_display %}">
+                    <th scope="row">{{ change.user|default:change.user_name }}</th>
+                    <td>{{ change.get_action_display|bettertitle }}</td>
+                    <td>{{ change.changed_object_type.name|bettertitle }}</td>
+                    <td>
+                      {% if change.changed_object.get_absolute_url %}
+                      <a class="text-body" href="{{ change.changed_object.get_absolute_url }}">{{ change.changed_object }}</a>
+                      {% else %} {{ change.changed_object|default:change.object_repr }} {% endif %}
+                    </td>
+
+                    <td>{{ change.time|date:'SHORT_DATETIME_FORMAT' }}</td>
+                    <td>
+                      <a role="button" class="text-body" href="{{ change.get_absolute_url }}">
+                        <i class="mdi mdi-dots-horizontal" data-bs-toggle="tooltip" data-bs-placement="left" title="View Change Details"></i>
+                      </a>
+                    </td>
+                  </tr>
+                {% endfor %}
+              </tbody>
+            </table>
+          {% elif perms.extras.view_objectchange %}
+            <div class="alert alert-secondary mt-4" role="alert">
+              No change history found.
+            </div>
+          {% endif %}
+
+        </div>
       </div>
     </div>
   </div>
-</div>
-{% endblock %}
+{% endblock content %}

+ 3 - 3
netbox/templates/import_success.html

@@ -1,9 +1,9 @@
-{% extends 'layout.html' %}
+{% extends 'base/layout.html' %}
 
 {% block title %}Import Completed{% endblock %}
 
 {% block content %}
-    {% include 'responsive_table.html' %}
+    {% include 'inc/responsive_table.html' %}
     {% if return_url %}
         <a href="{{ return_url }}" class="btn btn-outline-dark">View All</a>
     {% endif %}
@@ -11,4 +11,4 @@
         <span class="mdi mdi-database-import-outline" aria-hidden="true"></span>
         Import More
     </a>
-{% endblock %}
+{% endblock content %}

+ 0 - 0
netbox/templates/messages.html → netbox/templates/inc/messages.html


+ 0 - 0
netbox/templates/panel_table.html → netbox/templates/inc/panel_table.html


+ 0 - 0
netbox/templates/profile_button.html → netbox/templates/inc/profile_button.html


+ 0 - 0
netbox/templates/responsive_table.html → netbox/templates/inc/responsive_table.html


+ 1 - 1
netbox/templates/ipam/aggregate.html

@@ -77,7 +77,7 @@
 </div>
 <div class="row mb-3">
     <div class="col col-md-12">
-        {% include 'utilities/obj_table.html' with table=prefix_table table_template='panel_table.html' heading='Child Prefixes' bulk_edit_url='ipam:prefix_bulk_edit' bulk_delete_url='ipam:prefix_bulk_delete' %}
+        {% include 'utilities/obj_table.html' with table=prefix_table table_template='inc/panel_table.html' heading='Child Prefixes' bulk_edit_url='ipam:prefix_bulk_edit' bulk_delete_url='ipam:prefix_bulk_delete' %}
 	</div>
 </div>
 {% endblock %}

+ 2 - 2
netbox/templates/ipam/ipaddress.html

@@ -114,7 +114,7 @@
 	</div>
     
 	<div class="col col-md-8">
-        {% include 'panel_table.html' with table=parent_prefixes_table heading='Parent Prefixes' %}
+        {% include 'inc/panel_table.html' with table=parent_prefixes_table heading='Parent Prefixes' %}
         {% if duplicate_ips_table.rows %}
             {# Custom version of panel_table.html #}
             <div class="card bg-danger">
@@ -138,7 +138,7 @@
             </div>
         {% endif %}
         <div class="my-3">
-        {% include 'utilities/obj_table.html' with table=related_ips_table table_template='panel_table.html' heading='Related IP Addresses' %}
+        {% include 'utilities/obj_table.html' with table=related_ips_table table_template='inc/panel_table.html' heading='Related IP Addresses' %}
         </div>
         {% plugin_right_page object %}
 	</div>

+ 1 - 1
netbox/templates/ipam/ipaddress_assign.html

@@ -34,7 +34,7 @@
         <div class="row mb-3">
             <div class="col col-md-12">
                 <h3>Search Results</h3>
-                {% include 'utilities/obj_table.html' with table_template='panel_table.html' %}
+                {% include 'utilities/obj_table.html' with table_template='inc/panel_table.html' %}
             </div>
         </div>
     {% endif %}

+ 2 - 2
netbox/templates/ipam/prefix.html

@@ -117,9 +117,9 @@
     </div>
     <div class="col col-md-7">
         {% if duplicate_prefix_table.rows %}
-            {% include 'panel_table.html' with table=duplicate_prefix_table heading='Duplicate Prefixes' %}
+            {% include 'inc/panel_table.html' with table=duplicate_prefix_table heading='Duplicate Prefixes' %}
         {% endif %}
-        {% include 'panel_table.html' with table=parent_prefix_table heading='Parent Prefixes' %}
+        {% include 'inc/panel_table.html' with table=parent_prefix_table heading='Parent Prefixes' %}
         {% plugin_right_page object %}
     </div>
 </div>

+ 1 - 1
netbox/templates/ipam/prefix/ip_addresses.html

@@ -12,7 +12,7 @@
 {% block content %}
   <div class="row">
     <div class="col col-md-12">
-      {% include 'utilities/obj_table.html' with table=ip_table table_template='panel_table.html' heading='IP Addresses' bulk_edit_url='ipam:ipaddress_bulk_edit' bulk_delete_url='ipam:ipaddress_bulk_delete' %}
+      {% include 'utilities/obj_table.html' with table=ip_table table_template='inc/panel_table.html' heading='IP Addresses' bulk_edit_url='ipam:ipaddress_bulk_edit' bulk_delete_url='ipam:ipaddress_bulk_delete' %}
     </div>
   </div>
 {% endblock %}

+ 1 - 1
netbox/templates/ipam/prefix/prefixes.html

@@ -19,7 +19,7 @@
 {% block content %}
   <div class="row">
     <div class="col col-md-12">
-      {% include 'utilities/obj_table.html' with table=prefix_table table_template='panel_table.html' heading='Child Prefixes' bulk_edit_url='ipam:prefix_bulk_edit' bulk_delete_url='ipam:prefix_bulk_delete' parent=prefix %}
+      {% include 'utilities/obj_table.html' with table=prefix_table table_template='inc/panel_table.html' heading='Child Prefixes' bulk_edit_url='ipam:prefix_bulk_edit' bulk_delete_url='ipam:prefix_bulk_delete' parent=prefix %}
     </div>
   </div>
 {% endblock %}

+ 2 - 2
netbox/templates/ipam/routetarget.html

@@ -42,9 +42,9 @@
 	</div>
 	<div class="col col-md-6">
         <div class="mb-4">
-        {% include 'panel_table.html' with table=importing_vrfs_table heading="Importing VRFs" %}
+        {% include 'inc/panel_table.html' with table=importing_vrfs_table heading="Importing VRFs" %}
         </div>
-        {% include 'panel_table.html' with table=exporting_vrfs_table heading="Exporting VRFs" %}
+        {% include 'inc/panel_table.html' with table=exporting_vrfs_table heading="Exporting VRFs" %}
         {% plugin_right_page object %}
     </div>
 </div>

+ 1 - 1
netbox/templates/ipam/vlan.html

@@ -87,7 +87,7 @@
                     Prefixes
                 </h5>
                 <div class="card-body">
-                    {% include 'responsive_table.html' with table=prefix_table %}
+                    {% include 'inc/responsive_table.html' with table=prefix_table %}
                 </div>
                 {% if perms.ipam.add_prefix %}
                 <div class="card-footer text-end noprint">

+ 1 - 1
netbox/templates/ipam/vlan/interfaces.html

@@ -3,7 +3,7 @@
 {% block content %}
   <div class="row">
     <div class="col col-md-12">
-      {% include 'utilities/obj_table.html' with table=members_table table_template='panel_table.html' heading='Device Interfaces' parent=vlan %}
+      {% include 'utilities/obj_table.html' with table=members_table table_template='inc/panel_table.html' heading='Device Interfaces' parent=vlan %}
     </div>
   </div>
 {% endblock %}

+ 1 - 1
netbox/templates/ipam/vlan/vminterfaces.html

@@ -3,7 +3,7 @@
 {% block content %}
   <div class="row">
     <div class="col col-md-12">
-      {% include 'utilities/obj_table.html' with table=members_table table_template='panel_table.html' heading='Virtual Machine Interfaces' parent=vlan %}
+      {% include 'utilities/obj_table.html' with table=members_table table_template='inc/panel_table.html' heading='Virtual Machine Interfaces' parent=vlan %}
     </div>
   </div>
 {% endblock %}

+ 2 - 2
netbox/templates/ipam/vrf.html

@@ -66,8 +66,8 @@
         {% plugin_left_page object %}
 	</div>
 	<div class="col col-md-6">
-        {% include 'panel_table.html' with table=import_targets_table heading="Import Route Targets" %}
-        {% include 'panel_table.html' with table=export_targets_table heading="Export Route Targets" %}
+        {% include 'inc/panel_table.html' with table=import_targets_table heading="Import Route Targets" %}
+        {% include 'inc/panel_table.html' with table=export_targets_table heading="Export Route Targets" %}
         {% plugin_right_page object %}
     </div>
 </div>

+ 0 - 81
netbox/templates/layout.html

@@ -1,81 +0,0 @@
-{% extends 'base.html' %}
-{% load search_options %}
-
-{% block head %}{% endblock %}
-
-{% block layout %}
-<div class="container-fluid">
-  <div class="row">
-    <main class="col-md-9 ms-sm-auto col-lg-10 px-0">
-      <nav id="sidebar-menu" class="col-md-3 col-lg-2 d-md-block sidebar collapse px-0">
-        <div class="position-sticky pt-3">
-          <a class="px-2 sidebar-logo d-none d-md-flex" href="{% url 'home' %}">
-            {% load static %}
-            {% include 'logo.html' %}
-          </a>
-          <ul class="nav flex-column">
-            <div class="d-block d-md-none mx-1 my-3 search-container">
-              {% search_options %}
-            </div>
-            <div class="d-flex d-md-none mx-1 my-3 justify-content-end">
-              {% include './profile_button.html' %}
-            </div>
-            {% load nav %} {% nav %}
-          </ul>
-        </div>
-        {% include './bottom.html' %}
-      </nav>
-      <nav class="navbar navbar-light sticky-top flex-md-nowrap py-4 search container-fluid">
-        <div class="d-md-none w-100 d-flex justify-content-between align-items-center my-3">
-            <a class="px-2 sidebar-logo d-block d-md-none" href="{% url 'home' %}">
-              {% include 'logo.html' %}
-            </a>
-            <button
-              type="button"
-              aria-expanded="false"
-              data-bs-toggle="collapse"
-              aria-controls="sidebar-menu"
-              data-bs-target="#sidebar-menu"
-              aria-label="Toggle Navigation"
-              class="navbar-toggler position-relative collapsed"
-            >
-              <span class="navbar-toggler-icon"></span>
-            </button>
-          </div>
-          <div class="d-none d-md-flex w-100 search-container">
-            {% search_options %}
-            {% include './profile_button.html' %}
-          </div>
-      </nav>
-      
-      <div class="px-4 content-container">
-        {% block title_container %}
-        <div class="title-container">
-          <div id="content-title">
-            <h1 class="h2 w-100">{% block title %}{% endblock %}</h1>
-            {% block breadcrumb_main %}{% endblock %}
-          </div>
-
-          {% block controls %}{% endblock %}
-        </div>
-        {% endblock %}
-        <div id="content" class="container-fluid p-0 m-0">
-          {% block tabs %}{% endblock %}
-          {% block content %}{% endblock %}
-        </div>
-        <footer class="footer container-fluid pb-3 pt-4 px-0">
-          <div class="row align-items-center justify-content-end">
-          <div class="col-auto d-none d-md-block"></div>
-            <div class="col text-center text-md-end small text-muted">
-              <span class="fw-light d-block d-md-inline">{% now 'Y-m-d H:i:s T' %}</span>
-              <span class="ms-md-3 d-block d-md-inline">{{ settings.HOSTNAME }} (v{{ settings.VERSION }})</span>
-            </div>
-          </div>
-        </footer>
-      </div>
-    </main>
-  </div>
-</div>
-{% endblock %}
-{% block javascript %}{% endblock %}
-{% block data %}{% endblock %}

+ 58 - 52
netbox/templates/login.html

@@ -1,53 +1,58 @@
-{% extends 'base.html' %} {% load static %} {% block layout %}
-<main class="login-container text-center">
-  {% if settings.BANNER_LOGIN %}
-  <div class="alert alert-secondary" role="alert">
-    {{ settings.BANNER_LOGIN|safe }}
-  </div>
-  {% endif %}
-  <div class="form-login">
-    <form action="{% url 'login' %}" method="post">
-      <div class="mb-4">
-        {% include 'logo.html' with height=80 %}
+{# User login page. Extends base.html directly to override normal UI layout. #}
+{% extends 'base/base.html' %}
+{% load form_helpers %}
+{% load static %}
+
+{% block layout %}
+  <main class="login-container text-center">
+
+    {# Login banner #}
+    {% if settings.BANNER_LOGIN %}
+      <div class="alert alert-secondary" role="alert">
+        {{ settings.BANNER_LOGIN|safe }}
       </div>
-      {% csrf_token %} {% if 'next' in request.GET %}
-      <input type="hidden" name="next" value="{{ request.GET.next }}" />
-      {% endif %} {% if 'next' in request.POST %}
-      <input type="hidden" name="next" value="{{ request.POST.next }}" />
-      {% endif %}
-      <input
-        required
-        type="text"
-        placeholder="Username"
-        name="username"
-        maxlength="150"
-        id="id_username"
-        class="form-control"
-      />
-      <input
-        required
-        type="password"
-        placeholder="Password"
-        name="password"
-        id="id_password"
-        class="form-control"
-      />
-      <button type="submit" class="btn btn-primary btn-lg w-100 mt-4">
-        Sign In
-      </button>
-    </form>
-  </div>
-  {% load form_helpers %} {% if form.non_field_errors %}
-  <div class="alert alert-danger" role="alert">
-    <h4 class="alert-heading">Errors</h4>
-    <p>
-      {{ form.non_field_errors }}
-    </p>
-  </div>
-  {% endif %}
-</main>
-<footer class="footer container-fluid login-footer py-3">
-  <div class="row align-items-center">
+    {% endif %}
+
+    {# Login form #}
+    <div class="form-login">
+      <form action="{% url 'login' %}" method="post">
+        {% csrf_token %}
+
+        {# Logo #}
+        <div class="mb-4">
+          <img src="{% static 'netbox_logo.svg' %}" height="80" alt="NetBox logo" />
+        </div>
+
+        {# Set post-login URL #}
+        {% if 'next' in request.GET %}
+        <input type="hidden" name="next" value="{{ request.GET.next }}" />
+        {% endif %} {% if 'next' in request.POST %}
+        <input type="hidden" name="next" value="{{ request.POST.next }}" />
+        {% endif %}
+
+        {{ form.username }}
+        {{ form.password }}
+
+        <button type="submit" class="btn btn-primary btn-lg w-100 mt-4">
+          Sign In
+        </button>
+      </form>
+    </div>
+
+    {# Login form errors #}
+    {% if form.non_field_errors %}
+      <div class="alert alert-danger" role="alert">
+        <h4 class="alert-heading">Errors</h4>
+        <p>
+          {{ form.non_field_errors }}
+        </p>
+      </div>
+    {% endif %}
+  </main>
+
+  {# Page footer #}
+  <footer class="footer container-fluid login-footer py-3">
+    <div class="row align-items-center">
       <div class="col-2 col-md-1 mb-0">
         <button type="button" class="btn btn-sm color-mode-toggle" title="Toggle Color Mode">
           <i class="color-mode-icon mdi mdi-lightbulb"></i>&nbsp;
@@ -59,6 +64,7 @@
           {{ settings.HOSTNAME }} (v{{ settings.VERSION }})
         </small>
       </div>
-  </div>
-</footer>
-{% endblock %}
+    </div>
+  </footer>
+
+{% endblock layout %}

Разница между файлами не показана из-за своего большого размера
+ 0 - 18
netbox/templates/logo.html


+ 0 - 6
netbox/templates/rest_framework/api.html

@@ -1,10 +1,4 @@
 {% extends 'rest_framework/base.html' %}
-{% load static %}
-
-{% block bootstrap_theme %}
-    <link rel="stylesheet" type="text/css" href="{% static 'bootstrap-3.4.1-dist/css/bootstrap.min.css' %}"/>
-    <link rel="stylesheet" type="text/css" href="{% static "rest_framework/css/bootstrap-tweaks.css" %}"/>
-{% endblock %}
 
 {% block branding %}
     <a class="navbar-brand" href="/{{ settings.BASE_PATH }}">NetBox</a>

+ 3 - 3
netbox/templates/search.html

@@ -1,4 +1,4 @@
-{% extends 'layout.html' %}
+{% extends 'base/layout.html' %}
 {% load helpers %}
 {% load form_helpers %}
 
@@ -11,7 +11,7 @@
                 <div class="col col-md-9">
                     {% for obj_type in results %}
                         <h3 id="{{ obj_type.name|lower }}">{{ obj_type.name|bettertitle }}</h3>
-                        {% include 'panel_table.html' with table=obj_type.table %}
+                        {% include 'inc/panel_table.html' with table=obj_type.table %}
                         <a href="{{ obj_type.url }}" class="btn btn-primary float-end my-3">
                             <i class="mdi mdi-arrow-right-bold" aria-hidden="true"></i>
                             {% if obj_type.table.page.has_next %}
@@ -65,4 +65,4 @@
             </div>
         </div>
     {% endif %}
-{% endblock %}
+{% endblock content %}

+ 0 - 9
netbox/templates/search_form.html

@@ -1,9 +0,0 @@
-<div class="row" style="padding-bottom: 20px">
-    <div class="col col-md-12 text-center">
-        <form action="{% url 'search' %}" method="get" class="form-inline">
-            <input type="text" name="q" value="{{ request.GET.q }}" placeholder="Search" id="id_q" class="form-control" style="width: 350px" />
-            {{ search_form.obj_type }}
-            <button type="submit" class="btn btn-primary">Search</button>
-        </form>
-    </div>
-</div>

+ 1 - 1
netbox/templates/users/base.html

@@ -1,4 +1,4 @@
-{% extends 'layout.html' %}
+{% extends 'base/layout.html' %}
 
 {% block title %}{% endblock %}
 

+ 1 - 1
netbox/templates/utilities/confirmation_form.html

@@ -1,4 +1,4 @@
-{% extends 'layout.html' %}
+{% extends 'base/layout.html' %}
 {% load form_helpers %}
 
 {% block content %}

+ 2 - 2
netbox/templates/utilities/obj_table.html

@@ -27,7 +27,7 @@
                 </div>
             </div>
         {% endif %}
-        {% include table_template|default:'responsive_table.html' %}
+        {% include table_template|default:'inc/responsive_table.html' %}
         <div class="float-start noprint">
             {% block extra_actions %}{% endblock %}
             {% if bulk_edit_url and permissions.change %}
@@ -43,7 +43,7 @@
         </div>
     </form>
 {% else %}
-    {% include table_template|default:'responsive_table.html' %}
+    {% include table_template|default:'inc/responsive_table.html' %}
 {% endif %}
     {% include 'inc/paginator.html' with paginator=table.paginator page=table.page %}
 <div class="clearfix"></div>

+ 1 - 1
netbox/templates/virtualization/cluster/devices.html

@@ -11,7 +11,7 @@
       <form action="{% url 'virtualization:cluster_remove_devices' pk=object.pk %}" method="post">
       {% csrf_token %}
       <div class="card-body">
-        {% include 'responsive_table.html' with table=devices_table %}
+        {% include 'inc/responsive_table.html' with table=devices_table %}
       </div>
       {% if perms.virtualization.change_cluster %}
         <div class="card-footer noprint">

+ 1 - 1
netbox/templates/virtualization/cluster/virtual_machines.html

@@ -9,7 +9,7 @@
         Virtual Machines
       </h5>
       <div class="card-body">
-        {% include 'responsive_table.html' with table=virtualmachines_table %}
+        {% include 'inc/responsive_table.html' with table=virtualmachines_table %}
       </div>
     </div>
   </div>

+ 1 - 1
netbox/templates/virtualization/virtualmachine_component_add.html

@@ -1,4 +1,4 @@
-{% extends 'layout.html' %}
+{% extends 'base/layout.html' %}
 {% load helpers %}
 {% load form_helpers %}
 

+ 2 - 2
netbox/templates/virtualization/vminterface.html

@@ -102,12 +102,12 @@
 </div>
 <div class="row mb-3">
     <div class="col col-md-12">
-        {% include 'panel_table.html' with table=vlan_table heading="VLANs" %}
+        {% include 'inc/panel_table.html' with table=vlan_table heading="VLANs" %}
     </div>
 </div>
 <div class="row mb-3">
     <div class="col col-md-12">
-        {% include 'panel_table.html' with table=child_interfaces_table heading="Child Interfaces" %}
+        {% include 'inc/panel_table.html' with table=child_interfaces_table heading="Child Interfaces" %}
     </div>
 </div>
 <div class="row">

+ 1 - 6
netbox/users/forms.py

@@ -6,12 +6,7 @@ from .models import Token
 
 
 class LoginForm(BootstrapMixin, AuthenticationForm):
-
-    def __init__(self, *args, **kwargs):
-        super().__init__(*args, **kwargs)
-
-        self.fields['username'].widget.attrs['placeholder'] = ''
-        self.fields['password'].widget.attrs['placeholder'] = ''
+    pass
 
 
 class PasswordChangeForm(BootstrapMixin, DjangoPasswordChangeForm):

Некоторые файлы не были показаны из-за большого количества измененных файлов