From 3c2e0b0b173dc50ad50fd504a1e923dd1e3c3063 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Thu, 14 Jun 2018 16:15:14 -0400 Subject: [PATCH] Added changelog views --- netbox/circuits/urls.py | 5 + netbox/dcim/urls.py | 19 +- netbox/extras/admin.py | 4 +- netbox/extras/models.py | 5 + netbox/extras/views.py | 39 +++- netbox/ipam/urls.py | 11 ++ netbox/secrets/urls.py | 4 + netbox/templates/circuits/circuit.html | 87 +++++---- netbox/templates/circuits/provider.html | 97 +++++----- netbox/templates/dcim/device.html | 11 +- netbox/templates/dcim/devicetype.html | 67 ++++--- netbox/templates/dcim/rack.html | 93 +++++----- netbox/templates/dcim/site.html | 106 ++++++----- netbox/templates/extras/changelog.html | 36 ++++ netbox/templates/ipam/aggregate.html | 85 +++++---- netbox/templates/ipam/ipaddress.html | 89 +++++---- netbox/templates/ipam/prefix.html | 15 +- netbox/templates/ipam/vlan.html | 11 +- netbox/templates/ipam/vrf.html | 83 +++++---- netbox/templates/secrets/secret.html | 61 +++--- netbox/templates/tenancy/tenant.html | 89 +++++---- netbox/templates/virtualization/cluster.html | 89 +++++---- .../virtualization/virtualmachine.html | 173 ++++++++++-------- netbox/tenancy/urls.py | 4 + netbox/virtualization/urls.py | 6 + netbox/virtualization/views.py | 8 +- 26 files changed, 790 insertions(+), 507 deletions(-) create mode 100644 netbox/templates/extras/changelog.html diff --git a/netbox/circuits/urls.py b/netbox/circuits/urls.py index 569c1eb9a..6b5529a42 100644 --- a/netbox/circuits/urls.py +++ b/netbox/circuits/urls.py @@ -2,7 +2,9 @@ from __future__ import unicode_literals from django.conf.urls import url +from extras.views import ChangeLogView from . import views +from .models import Circuit, CircuitType, Provider app_name = 'circuits' urlpatterns = [ @@ -16,6 +18,7 @@ urlpatterns = [ url(r'^providers/(?P[\w-]+)/$', views.ProviderView.as_view(), name='provider'), url(r'^providers/(?P[\w-]+)/edit/$', views.ProviderEditView.as_view(), name='provider_edit'), url(r'^providers/(?P[\w-]+)/delete/$', views.ProviderDeleteView.as_view(), name='provider_delete'), + url(r'^providers/(?P[\w-]+)/changelog/$', ChangeLogView.as_view(), name='provider_changelog', kwargs={'model': Provider}), # Circuit types url(r'^circuit-types/$', views.CircuitTypeListView.as_view(), name='circuittype_list'), @@ -23,6 +26,7 @@ urlpatterns = [ url(r'^circuit-types/import/$', views.CircuitTypeBulkImportView.as_view(), name='circuittype_import'), url(r'^circuit-types/delete/$', views.CircuitTypeBulkDeleteView.as_view(), name='circuittype_bulk_delete'), url(r'^circuit-types/(?P[\w-]+)/edit/$', views.CircuitTypeEditView.as_view(), name='circuittype_edit'), + url(r'^circuit-types/(?P[\w-]+)/changelog/$', ChangeLogView.as_view(), name='circuittype_changelog', kwargs={'model': CircuitType}), # Circuits url(r'^circuits/$', views.CircuitListView.as_view(), name='circuit_list'), @@ -33,6 +37,7 @@ urlpatterns = [ url(r'^circuits/(?P\d+)/$', views.CircuitView.as_view(), name='circuit'), url(r'^circuits/(?P\d+)/edit/$', views.CircuitEditView.as_view(), name='circuit_edit'), url(r'^circuits/(?P\d+)/delete/$', views.CircuitDeleteView.as_view(), name='circuit_delete'), + url(r'^circuits/(?P\d+)/changelog/$', ChangeLogView.as_view(), name='circuit_changelog', kwargs={'model': Circuit}), url(r'^circuits/(?P\d+)/terminations/swap/$', views.circuit_terminations_swap, name='circuit_terminations_swap'), # Circuit terminations diff --git a/netbox/dcim/urls.py b/netbox/dcim/urls.py index 5682bd8e7..67e957f9b 100644 --- a/netbox/dcim/urls.py +++ b/netbox/dcim/urls.py @@ -2,11 +2,14 @@ from __future__ import unicode_literals from django.conf.urls import url -from extras.views import ImageAttachmentEditView +from extras.views import ChangeLogView, ImageAttachmentEditView from ipam.views import ServiceCreateView from secrets.views import secret_add from . import views -from .models import Device, Rack, Site +from .models import ( + Device, DeviceRole, DeviceType, Manufacturer, Platform, Rack, RackGroup, RackReservation, RackRole, Region, Site, + VirtualChassis, +) app_name = 'dcim' urlpatterns = [ @@ -17,6 +20,7 @@ urlpatterns = [ url(r'^regions/import/$', views.RegionBulkImportView.as_view(), name='region_import'), url(r'^regions/delete/$', views.RegionBulkDeleteView.as_view(), name='region_bulk_delete'), url(r'^regions/(?P\d+)/edit/$', views.RegionEditView.as_view(), name='region_edit'), + url(r'^regions/(?P\d+)/changelog/$', ChangeLogView.as_view(), name='region_changelog', kwargs={'model': Region}), # Sites url(r'^sites/$', views.SiteListView.as_view(), name='site_list'), @@ -26,6 +30,7 @@ urlpatterns = [ url(r'^sites/(?P[\w-]+)/$', views.SiteView.as_view(), name='site'), url(r'^sites/(?P[\w-]+)/edit/$', views.SiteEditView.as_view(), name='site_edit'), url(r'^sites/(?P[\w-]+)/delete/$', views.SiteDeleteView.as_view(), name='site_delete'), + url(r'^sites/(?P[\w-]+)/changelog/$', ChangeLogView.as_view(), name='site_changelog', kwargs={'model': Site}), url(r'^sites/(?P\d+)/images/add/$', ImageAttachmentEditView.as_view(), name='site_add_image', kwargs={'model': Site}), # Rack groups @@ -34,6 +39,7 @@ urlpatterns = [ url(r'^rack-groups/import/$', views.RackGroupBulkImportView.as_view(), name='rackgroup_import'), url(r'^rack-groups/delete/$', views.RackGroupBulkDeleteView.as_view(), name='rackgroup_bulk_delete'), url(r'^rack-groups/(?P\d+)/edit/$', views.RackGroupEditView.as_view(), name='rackgroup_edit'), + url(r'^rack-groups/(?P\d+)/changelog/$', ChangeLogView.as_view(), name='rackgroup_changelog', kwargs={'model': RackGroup}), # Rack roles url(r'^rack-roles/$', views.RackRoleListView.as_view(), name='rackrole_list'), @@ -41,6 +47,7 @@ urlpatterns = [ url(r'^rack-roles/import/$', views.RackRoleBulkImportView.as_view(), name='rackrole_import'), url(r'^rack-roles/delete/$', views.RackRoleBulkDeleteView.as_view(), name='rackrole_bulk_delete'), url(r'^rack-roles/(?P\d+)/edit/$', views.RackRoleEditView.as_view(), name='rackrole_edit'), + url(r'^rack-roles/(?P\d+)/changelog/$', ChangeLogView.as_view(), name='rackrole_changelog', kwargs={'model': RackRole}), # Rack reservations url(r'^rack-reservations/$', views.RackReservationListView.as_view(), name='rackreservation_list'), @@ -48,6 +55,7 @@ urlpatterns = [ url(r'^rack-reservations/delete/$', views.RackReservationBulkDeleteView.as_view(), name='rackreservation_bulk_delete'), url(r'^rack-reservations/(?P\d+)/edit/$', views.RackReservationEditView.as_view(), name='rackreservation_edit'), url(r'^rack-reservations/(?P\d+)/delete/$', views.RackReservationDeleteView.as_view(), name='rackreservation_delete'), + url(r'^rack-reservations/(?P\d+)/changelog/$', ChangeLogView.as_view(), name='rackreservation_changelog', kwargs={'model': RackReservation}), # Racks url(r'^racks/$', views.RackListView.as_view(), name='rack_list'), @@ -59,6 +67,7 @@ urlpatterns = [ url(r'^racks/(?P\d+)/$', views.RackView.as_view(), name='rack'), url(r'^racks/(?P\d+)/edit/$', views.RackEditView.as_view(), name='rack_edit'), url(r'^racks/(?P\d+)/delete/$', views.RackDeleteView.as_view(), name='rack_delete'), + url(r'^racks/(?P\d+)/changelog/$', ChangeLogView.as_view(), name='rack_changelog', kwargs={'model': Rack}), url(r'^racks/(?P\d+)/reservations/add/$', views.RackReservationCreateView.as_view(), name='rack_add_reservation'), url(r'^racks/(?P\d+)/images/add/$', ImageAttachmentEditView.as_view(), name='rack_add_image', kwargs={'model': Rack}), @@ -68,6 +77,7 @@ urlpatterns = [ url(r'^manufacturers/import/$', views.ManufacturerBulkImportView.as_view(), name='manufacturer_import'), url(r'^manufacturers/delete/$', views.ManufacturerBulkDeleteView.as_view(), name='manufacturer_bulk_delete'), url(r'^manufacturers/(?P[\w-]+)/edit/$', views.ManufacturerEditView.as_view(), name='manufacturer_edit'), + url(r'^manufacturers/(?P[\w-]+)/changelog/$', ChangeLogView.as_view(), name='manufacturer_changelog', kwargs={'model': Manufacturer}), # Device types url(r'^device-types/$', views.DeviceTypeListView.as_view(), name='devicetype_list'), @@ -78,6 +88,7 @@ urlpatterns = [ url(r'^device-types/(?P\d+)/$', views.DeviceTypeView.as_view(), name='devicetype'), url(r'^device-types/(?P\d+)/edit/$', views.DeviceTypeEditView.as_view(), name='devicetype_edit'), url(r'^device-types/(?P\d+)/delete/$', views.DeviceTypeDeleteView.as_view(), name='devicetype_delete'), + url(r'^device-types/(?P\d+)/changelog/$', ChangeLogView.as_view(), name='devicetype_changelog', kwargs={'model': DeviceType}), # Console port templates url(r'^device-types/(?P\d+)/console-ports/add/$', views.ConsolePortTemplateCreateView.as_view(), name='devicetype_add_consoleport'), @@ -110,6 +121,7 @@ urlpatterns = [ url(r'^device-roles/import/$', views.DeviceRoleBulkImportView.as_view(), name='devicerole_import'), url(r'^device-roles/delete/$', views.DeviceRoleBulkDeleteView.as_view(), name='devicerole_bulk_delete'), url(r'^device-roles/(?P[\w-]+)/edit/$', views.DeviceRoleEditView.as_view(), name='devicerole_edit'), + url(r'^device-roles/(?P[\w-]+)/changelog/$', ChangeLogView.as_view(), name='devicerole_changelog', kwargs={'model': DeviceRole}), # Platforms url(r'^platforms/$', views.PlatformListView.as_view(), name='platform_list'), @@ -117,6 +129,7 @@ urlpatterns = [ url(r'^platforms/import/$', views.PlatformBulkImportView.as_view(), name='platform_import'), url(r'^platforms/delete/$', views.PlatformBulkDeleteView.as_view(), name='platform_bulk_delete'), url(r'^platforms/(?P[\w-]+)/edit/$', views.PlatformEditView.as_view(), name='platform_edit'), + url(r'^platforms/(?P[\w-]+)/changelog/$', ChangeLogView.as_view(), name='platform_changelog', kwargs={'model': Platform}), # Devices url(r'^devices/$', views.DeviceListView.as_view(), name='device_list'), @@ -128,6 +141,7 @@ urlpatterns = [ url(r'^devices/(?P\d+)/$', views.DeviceView.as_view(), name='device'), url(r'^devices/(?P\d+)/edit/$', views.DeviceEditView.as_view(), name='device_edit'), url(r'^devices/(?P\d+)/delete/$', views.DeviceDeleteView.as_view(), name='device_delete'), + url(r'^devices/(?P\d+)/changelog/$', ChangeLogView.as_view(), name='device_changelog', kwargs={'model': Device}), url(r'^devices/(?P\d+)/inventory/$', views.DeviceInventoryView.as_view(), name='device_inventory'), url(r'^devices/(?P\d+)/status/$', views.DeviceStatusView.as_view(), name='device_status'), url(r'^devices/(?P\d+)/lldp-neighbors/$', views.DeviceLLDPNeighborsView.as_view(), name='device_lldp_neighbors'), @@ -221,6 +235,7 @@ urlpatterns = [ url(r'^virtual-chassis/add/$', views.VirtualChassisCreateView.as_view(), name='virtualchassis_add'), url(r'^virtual-chassis/(?P\d+)/edit/$', views.VirtualChassisEditView.as_view(), name='virtualchassis_edit'), url(r'^virtual-chassis/(?P\d+)/delete/$', views.VirtualChassisDeleteView.as_view(), name='virtualchassis_delete'), + url(r'^virtual-chassis/(?P\d+)/changelog/$', ChangeLogView.as_view(), name='virtualchassis_changelog', kwargs={'model': VirtualChassis}), url(r'^virtual-chassis/(?P\d+)/add-member/$', views.VirtualChassisAddMemberView.as_view(), name='virtualchassis_add_member'), url(r'^virtual-chassis-members/(?P\d+)/delete/$', views.VirtualChassisRemoveMemberView.as_view(), name='virtualchassis_remove_member'), diff --git a/netbox/extras/admin.py b/netbox/extras/admin.py index 200387f88..3da723b7d 100644 --- a/netbox/extras/admin.py +++ b/netbox/extras/admin.py @@ -132,7 +132,7 @@ class TopologyMapAdmin(admin.ModelAdmin): @admin.register(ObjectChange) class ObjectChangeAdmin(admin.ModelAdmin): actions = None - fields = ['time', 'content_type', 'display_object', 'action', 'display_user'] + fields = ['time', 'content_type', 'display_object', 'action', 'display_user', 'object_data'] list_display = ['time', 'content_type', 'display_object', 'display_action', 'display_user'] list_filter = ['time', 'action', 'user__username'] list_select_related = ['content_type', 'user'] @@ -156,7 +156,7 @@ class ObjectChangeAdmin(admin.ModelAdmin): OBJECTCHANGE_ACTION_DELETE: 'deletelink', } return mark_safe('{}'.format(icon[obj.action], obj.get_action_display())) - display_user.short_description = 'action' + display_action.short_description = 'action' def display_object(self, obj): if hasattr(obj.changed_object, 'get_absolute_url'): diff --git a/netbox/extras/models.py b/netbox/extras/models.py index e9fb2d543..759f90b4b 100644 --- a/netbox/extras/models.py +++ b/netbox/extras/models.py @@ -2,6 +2,7 @@ from __future__ import unicode_literals from collections import OrderedDict from datetime import date +import json import graphviz from django.contrib.auth.models import User @@ -720,6 +721,10 @@ class ObjectChange(models.Model): return super(ObjectChange, self).save(*args, **kwargs) + @property + def object_data_pretty(self): + return json.dumps(self.object_data, indent=4, sort_keys=True) + # # User actions diff --git a/netbox/extras/views.py b/netbox/extras/views.py index 130437356..d3dd2c3d2 100644 --- a/netbox/extras/views.py +++ b/netbox/extras/views.py @@ -1,7 +1,9 @@ from __future__ import unicode_literals +from django import template from django.contrib import messages from django.contrib.auth.mixins import PermissionRequiredMixin +from django.contrib.contenttypes.models import ContentType from django.db.models import Count from django.http import Http404 from django.shortcuts import get_object_or_404, redirect, render, reverse @@ -12,7 +14,7 @@ from taggit.models import Tag from utilities.forms import ConfirmationForm from utilities.views import BulkDeleteView, ObjectDeleteView, ObjectEditView, ObjectListView from .forms import ImageAttachmentForm, TagForm -from .models import ImageAttachment, ReportResult, UserAction +from .models import ImageAttachment, ObjectChange, ReportResult, UserAction from .reports import get_report, get_reports from .tables import TagTable @@ -50,6 +52,41 @@ class TagBulkDeleteView(PermissionRequiredMixin, BulkDeleteView): default_return_url = 'extras:tag_list' +# +# Change logging +# + +class ChangeLogView(View): + """ + Present a history of changes made to an object. + """ + + def get(self, request, model, **kwargs): + + # Get object my model and kwargs (e.g. slug='foo') + obj = get_object_or_404(model, **kwargs) + + # Gather all changes for this object + content_type = ContentType.objects.get_for_model(model) + changes = ObjectChange.objects.filter(content_type=content_type, object_id=obj.pk) + + # Check whether a header template exists for this model + base_template = '{}/{}.html'.format(model._meta.app_label, model._meta.model_name) + try: + template.loader.get_template(base_template) + object_var = model._meta.model_name + except template.TemplateDoesNotExist: + base_template = '_base.html' + object_var = 'obj' + + return render(request, 'extras/changelog.html', { + object_var: obj, + 'changes': changes, + 'base_template': base_template, + 'active_tab': 'changelog', + }) + + # # Image attachments # diff --git a/netbox/ipam/urls.py b/netbox/ipam/urls.py index aa7c17a5c..89c30a6db 100644 --- a/netbox/ipam/urls.py +++ b/netbox/ipam/urls.py @@ -2,7 +2,9 @@ from __future__ import unicode_literals from django.conf.urls import url +from extras.views import ChangeLogView from . import views +from .models import Aggregate, IPAddress, Prefix, RIR, Role, Service, VLAN, VLANGroup, VRF app_name = 'ipam' @@ -17,6 +19,7 @@ urlpatterns = [ url(r'^vrfs/(?P\d+)/$', views.VRFView.as_view(), name='vrf'), url(r'^vrfs/(?P\d+)/edit/$', views.VRFEditView.as_view(), name='vrf_edit'), url(r'^vrfs/(?P\d+)/delete/$', views.VRFDeleteView.as_view(), name='vrf_delete'), + url(r'^vrfs/(?P\d+)/changelog/$', ChangeLogView.as_view(), name='vrf_changelog', kwargs={'model': VRF}), # RIRs url(r'^rirs/$', views.RIRListView.as_view(), name='rir_list'), @@ -24,6 +27,7 @@ urlpatterns = [ url(r'^rirs/import/$', views.RIRBulkImportView.as_view(), name='rir_import'), url(r'^rirs/delete/$', views.RIRBulkDeleteView.as_view(), name='rir_bulk_delete'), url(r'^rirs/(?P[\w-]+)/edit/$', views.RIREditView.as_view(), name='rir_edit'), + url(r'^vrfs/(?P[\w-]+)/changelog/$', ChangeLogView.as_view(), name='rir_changelog', kwargs={'model': RIR}), # Aggregates url(r'^aggregates/$', views.AggregateListView.as_view(), name='aggregate_list'), @@ -34,6 +38,7 @@ urlpatterns = [ url(r'^aggregates/(?P\d+)/$', views.AggregateView.as_view(), name='aggregate'), url(r'^aggregates/(?P\d+)/edit/$', views.AggregateEditView.as_view(), name='aggregate_edit'), url(r'^aggregates/(?P\d+)/delete/$', views.AggregateDeleteView.as_view(), name='aggregate_delete'), + url(r'^aggregates/(?P\d+)/changelog/$', ChangeLogView.as_view(), name='aggregate_changelog', kwargs={'model': Aggregate}), # Roles url(r'^roles/$', views.RoleListView.as_view(), name='role_list'), @@ -41,6 +46,7 @@ urlpatterns = [ url(r'^roles/import/$', views.RoleBulkImportView.as_view(), name='role_import'), url(r'^roles/delete/$', views.RoleBulkDeleteView.as_view(), name='role_bulk_delete'), url(r'^roles/(?P[\w-]+)/edit/$', views.RoleEditView.as_view(), name='role_edit'), + url(r'^roles/(?P[\w-]+)/changelog/$', ChangeLogView.as_view(), name='role_changelog', kwargs={'model': Role}), # Prefixes url(r'^prefixes/$', views.PrefixListView.as_view(), name='prefix_list'), @@ -51,6 +57,7 @@ urlpatterns = [ url(r'^prefixes/(?P\d+)/$', views.PrefixView.as_view(), name='prefix'), url(r'^prefixes/(?P\d+)/edit/$', views.PrefixEditView.as_view(), name='prefix_edit'), url(r'^prefixes/(?P\d+)/delete/$', views.PrefixDeleteView.as_view(), name='prefix_delete'), + url(r'^prefixes/(?P\d+)/changelog/$', ChangeLogView.as_view(), name='prefix_changelog', kwargs={'model': Prefix}), url(r'^prefixes/(?P\d+)/prefixes/$', views.PrefixPrefixesView.as_view(), name='prefix_prefixes'), url(r'^prefixes/(?P\d+)/ip-addresses/$', views.PrefixIPAddressesView.as_view(), name='prefix_ipaddresses'), @@ -61,6 +68,7 @@ urlpatterns = [ url(r'^ip-addresses/import/$', views.IPAddressBulkImportView.as_view(), name='ipaddress_import'), url(r'^ip-addresses/edit/$', views.IPAddressBulkEditView.as_view(), name='ipaddress_bulk_edit'), url(r'^ip-addresses/delete/$', views.IPAddressBulkDeleteView.as_view(), name='ipaddress_bulk_delete'), + url(r'^ip-addresses/(?P\d+)/changelog/$', ChangeLogView.as_view(), name='ipaddress_changelog', kwargs={'model': IPAddress}), url(r'^ip-addresses/assign/$', views.IPAddressAssignView.as_view(), name='ipaddress_assign'), url(r'^ip-addresses/(?P\d+)/$', views.IPAddressView.as_view(), name='ipaddress'), url(r'^ip-addresses/(?P\d+)/edit/$', views.IPAddressEditView.as_view(), name='ipaddress_edit'), @@ -72,6 +80,7 @@ urlpatterns = [ url(r'^vlan-groups/import/$', views.VLANGroupBulkImportView.as_view(), name='vlangroup_import'), url(r'^vlan-groups/delete/$', views.VLANGroupBulkDeleteView.as_view(), name='vlangroup_bulk_delete'), url(r'^vlan-groups/(?P\d+)/edit/$', views.VLANGroupEditView.as_view(), name='vlangroup_edit'), + url(r'^vlan-groups/(?P\d+)/changelog/$', ChangeLogView.as_view(), name='vlangroup_changelog', kwargs={'model': VLANGroup}), # VLANs url(r'^vlans/$', views.VLANListView.as_view(), name='vlan_list'), @@ -83,9 +92,11 @@ urlpatterns = [ url(r'^vlans/(?P\d+)/members/$', views.VLANMembersView.as_view(), name='vlan_members'), url(r'^vlans/(?P\d+)/edit/$', views.VLANEditView.as_view(), name='vlan_edit'), url(r'^vlans/(?P\d+)/delete/$', views.VLANDeleteView.as_view(), name='vlan_delete'), + url(r'^vlans/(?P\d+)/changelog/$', ChangeLogView.as_view(), name='vlan_changelog', kwargs={'model': VLAN}), # Services url(r'^services/(?P\d+)/edit/$', views.ServiceEditView.as_view(), name='service_edit'), url(r'^services/(?P\d+)/delete/$', views.ServiceDeleteView.as_view(), name='service_delete'), + url(r'^services/(?P\d+)/changelog/$', ChangeLogView.as_view(), name='service_changelog', kwargs={'model': Service}), ] diff --git a/netbox/secrets/urls.py b/netbox/secrets/urls.py index cd6415719..9c9324c4a 100644 --- a/netbox/secrets/urls.py +++ b/netbox/secrets/urls.py @@ -2,7 +2,9 @@ from __future__ import unicode_literals from django.conf.urls import url +from extras.views import ChangeLogView from . import views +from .models import Secret, SecretRole app_name = 'secrets' urlpatterns = [ @@ -13,6 +15,7 @@ urlpatterns = [ url(r'^secret-roles/import/$', views.SecretRoleBulkImportView.as_view(), name='secretrole_import'), url(r'^secret-roles/delete/$', views.SecretRoleBulkDeleteView.as_view(), name='secretrole_bulk_delete'), url(r'^secret-roles/(?P[\w-]+)/edit/$', views.SecretRoleEditView.as_view(), name='secretrole_edit'), + url(r'^secret-roles/(?P[\w-]+)/changelog/$', ChangeLogView.as_view(), name='secretrole_changelog', kwargs={'model': SecretRole}), # Secrets url(r'^secrets/$', views.SecretListView.as_view(), name='secret_list'), @@ -22,5 +25,6 @@ urlpatterns = [ url(r'^secrets/(?P\d+)/$', views.SecretView.as_view(), name='secret'), url(r'^secrets/(?P\d+)/edit/$', views.secret_edit, name='secret_edit'), url(r'^secrets/(?P\d+)/delete/$', views.SecretDeleteView.as_view(), name='secret_delete'), + url(r'^secrets/(?P\d+)/changelog/$', ChangeLogView.as_view(), name='secret_changelog', kwargs={'model': Secret}), ] diff --git a/netbox/templates/circuits/circuit.html b/netbox/templates/circuits/circuit.html index 509c6da89..048c16862 100644 --- a/netbox/templates/circuits/circuit.html +++ b/netbox/templates/circuits/circuit.html @@ -1,44 +1,57 @@ {% extends '_base.html' %} {% load helpers %} +{% block title %}{{ circuit }}{% endblock %} + +{% block header %} +
+
+ +
+
+
+
+ + + + +
+
+
+
+
+ {% if perms.circuits.change_circuit %} + + + Edit this circuit + + {% endif %} + {% if perms.circuits.delete_circuit %} + + + Delete this circuit + + {% endif %} +
+

{{ circuit }}

+ {% include 'inc/created_updated.html' with obj=circuit %} + +{% endblock %} + {% block content %} -
-
- -
-
-
-
- - - - -
-
-
-
-
- {% if perms.circuits.change_circuit %} - - - Edit this circuit - - {% endif %} - {% if perms.circuits.delete_circuit %} - - - Delete this circuit - - {% endif %} -
-

{% block title %}{{ circuit.provider }} - {{ circuit.cid }}{% endblock %}

-{% include 'inc/created_updated.html' with obj=circuit %}
diff --git a/netbox/templates/circuits/provider.html b/netbox/templates/circuits/provider.html index e19175c7f..d2fed8647 100644 --- a/netbox/templates/circuits/provider.html +++ b/netbox/templates/circuits/provider.html @@ -2,49 +2,62 @@ {% load static from staticfiles %} {% load helpers %} +{% block title %}{{ provider }}{% endblock %} + +{% block header %} +
+
+ +
+
+
+
+ + + + +
+
+
+
+
+ {% if show_graphs %} + + {% endif %} + {% if perms.circuits.change_provider %} + + + Edit this provider + + {% endif %} + {% if perms.circuits.delete_provider %} + + + Delete this provider + + {% endif %} +
+

{{ provider }}

+ {% include 'inc/created_updated.html' with obj=provider %} + +{% endblock %} + {% block content %} -
-
- -
-
-
-
- - - - -
-
-
-
-
- {% if show_graphs %} - - {% endif %} - {% if perms.circuits.change_provider %} - - - Edit this provider - - {% endif %} - {% if perms.circuits.delete_provider %} - - - Delete this provider - - {% endif %} -
-

{% block title %}{{ provider }}{% endblock %}

-{% include 'inc/created_updated.html' with obj=provider %}
diff --git a/netbox/templates/dcim/device.html b/netbox/templates/dcim/device.html index 0cc1e4cf8..1c1539f89 100644 --- a/netbox/templates/dcim/device.html +++ b/netbox/templates/dcim/device.html @@ -2,6 +2,8 @@ {% load static from staticfiles %} {% load helpers %} +{% block title %}{{ device }}{% endblock %} + {% block header %}
@@ -45,11 +47,11 @@ {% endif %}
-

{% block title %}{{ device }}{% endblock %}

+

{{ device }}

{% include 'inc/created_updated.html' with obj=device %} -