Skip to content

Commit eb9a804

Browse files
committed
#12591: Add a dedicated view for the active config revision
1 parent 210d7bb commit eb9a804

File tree

7 files changed

+66
-45
lines changed

7 files changed

+66
-45
lines changed

netbox/core/urls.py

+3
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,7 @@
2525
path('jobs/<int:pk>/', views.JobView.as_view(), name='job'),
2626
path('jobs/<int:pk>/delete/', views.JobDeleteView.as_view(), name='job_delete'),
2727

28+
# Configuration
29+
path('config/', views.ConfigView.as_view(), name='config'),
30+
2831
)

netbox/core/views.py

+12
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from django.contrib import messages
22
from django.shortcuts import get_object_or_404, redirect
33

4+
from extras.models import ConfigRevision
45
from netbox.views import generic
56
from netbox.views.generic.base import BaseObjectView
67
from utilities.utils import count_related
@@ -141,3 +142,14 @@ class JobBulkDeleteView(generic.BulkDeleteView):
141142
queryset = Job.objects.all()
142143
filterset = filtersets.JobFilterSet
143144
table = tables.JobTable
145+
146+
147+
#
148+
# Config Revisions
149+
#
150+
151+
class ConfigView(generic.ObjectView):
152+
queryset = ConfigRevision.objects.all()
153+
154+
def get_object(self, **kwargs):
155+
return self.queryset.first()

netbox/extras/forms/model_forms.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -490,7 +490,9 @@ class ConfigRevisionForm(BootstrapMixin, forms.ModelForm, metaclass=ConfigFormMe
490490
(_('Pagination'), ('PAGINATE_COUNT', 'MAX_PAGE_SIZE')),
491491
(_('Validation'), ('CUSTOM_VALIDATORS',)),
492492
(_('User Preferences'), ('DEFAULT_USER_PREFERENCES',)),
493-
(_('Miscellaneous'), ('MAINTENANCE_MODE', 'GRAPHQL_ENABLED', 'CHANGELOG_RETENTION', 'JOB_RETENTION', 'MAPS_URL')),
493+
(_('Miscellaneous'), (
494+
'MAINTENANCE_MODE', 'GRAPHQL_ENABLED', 'CHANGELOG_RETENTION', 'JOB_RETENTION', 'MAPS_URL',
495+
)),
494496
(_('Config Revision'), ('comment',))
495497
)
496498

@@ -524,6 +526,8 @@ def __init__(self, *args, **kwargs):
524526
elif value == param.default:
525527
help_text += _(' (default)')
526528
self.fields[param.name].help_text = help_text
529+
if type(value) in (tuple, list):
530+
value = ', '.join(value)
527531
self.fields[param.name].initial = value
528532
if is_static:
529533
self.fields[param.name].disabled = True

netbox/extras/models/models.py

+5-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import json
22
import urllib.parse
33

4-
from django.contrib import admin
54
from django.conf import settings
65
from django.contrib.contenttypes.fields import GenericForeignKey
76
from django.contrib.contenttypes.models import ContentType
@@ -12,7 +11,7 @@
1211
from django.urls import reverse
1312
from django.utils import timezone
1413
from django.utils.formats import date_format
15-
from django.utils.translation import gettext_lazy as _
14+
from django.utils.translation import gettext, gettext_lazy as _
1615
from rest_framework.utils.encoders import JSONEncoder
1716

1817
from extras.choices import *
@@ -724,7 +723,9 @@ class Meta:
724723
verbose_name_plural = _('config revisions')
725724

726725
def __str__(self):
727-
return f'Config revision #{self.pk} ({self.created})'
726+
if self.is_active:
727+
return gettext('Current configuration')
728+
return gettext('Config revision #{id}').format(id=self.pk)
728729

729730
def __getattr__(self, item):
730731
if item in self.data:
@@ -742,6 +743,6 @@ def activate(self):
742743
cache.set('config_version', self.pk, None)
743744
activate.alters_data = True
744745

745-
@admin.display(boolean=True)
746+
@property
746747
def is_active(self):
747748
return cache.get('config_version') == self.pk

netbox/netbox/config/parameters.py

-2
Original file line numberDiff line numberDiff line change
@@ -102,15 +102,13 @@ def __init__(self, name, label, default, description='', field=None, field_kwarg
102102
description=_("Default voltage for powerfeeds"),
103103
field=forms.IntegerField
104104
),
105-
106105
ConfigParam(
107106
name='POWERFEED_DEFAULT_AMPERAGE',
108107
label=_('Powerfeed amperage'),
109108
default=15,
110109
description=_("Default amperage for powerfeeds"),
111110
field=forms.IntegerField
112111
),
113-
114112
ConfigParam(
115113
name='POWERFEED_DEFAULT_MAX_UTILIZATION',
116114
label=_('Powerfeed max utilization'),

netbox/netbox/navigation/menu.py

+5
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,11 @@
406406
MenuGroup(
407407
label=_('Configuration'),
408408
items=(
409+
MenuItem(
410+
link='core:config',
411+
link_text=_('Current Config'),
412+
permissions=['extras.view_configrevision']
413+
),
409414
MenuItem(
410415
link='extras:configrevision_list',
411416
link_text=_('Config Revisions'),

netbox/templates/extras/configrevision.html

+36-38
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,13 @@
1414
<div class="controls">
1515
<div class="control-group">
1616
{% plugin_buttons object %}
17+
{% if object.is_active and perms.extras.add_configrevision %}
18+
{% url 'extras:configrevision_add' as edit_url %}
19+
{% include "buttons/edit.html" with url=edit_url %}
20+
{% endif %}
21+
{% if not object.is_active and perms.extras.delete_configrevision %}
22+
{% delete_button object %}
23+
{% endif %}
1724
</div>
1825
<div class="control-group">
1926
{% custom_links object %}
@@ -23,37 +30,37 @@
2330

2431
{% block content %}
2532
<div class="row">
26-
<div class="col col-md-6">
33+
<div class="col col-md-12">
2734
<div class="card">
28-
<h5 class="card-header">{% trans "Rack Elevation" %}</h5>
35+
<h5 class="card-header">{% trans "Rack Elevations" %}</h5>
2936
<div class="card-body">
3037
<table class="table table-hover attr-table">
3138
<tr>
32-
<th scope="row">{% trans "Rack elevation default unit height" %}:</th>
39+
<th scope="row">{% trans "Default unit height" %}</th>
3340
<td>{{ object.data.RACK_ELEVATION_DEFAULT_UNIT_HEIGHT }}</td>
3441
</tr>
3542
<tr>
36-
<th scope="row">{% trans "Rack elevation default unit width" %}:</th>
43+
<th scope="row">{% trans "Default unit width" %}</th>
3744
<td>{{ object.data.RACK_ELEVATION_DEFAULT_UNIT_WIDTH }}</td>
3845
</tr>
3946
</table>
4047
</div>
4148
</div>
4249

4350
<div class="card">
44-
<h5 class="card-header">{% trans "Power" %}</h5>
51+
<h5 class="card-header">{% trans "Power Feeds" %}</h5>
4552
<div class="card-body">
4653
<table class="table table-hover attr-table">
4754
<tr>
48-
<th scope="row">{% trans "Powerfeed default voltage" %}:</th>
55+
<th scope="row">{% trans "Default voltage" %}</th>
4956
<td>{{ object.data.POWERFEED_DEFAULT_VOLTAGE }}</td>
5057
</tr>
5158
<tr>
52-
<th scope="row">{% trans "Powerfeed default amperage" %}:</th>
59+
<th scope="row">{% trans "Default amperage" %}</th>
5360
<td>{{ object.data.POWERFEED_DEFAULT_AMPERAGE }}</td>
5461
</tr>
5562
<tr>
56-
<th scope="row">{% trans "Powerfeed default max utilization" %}:</th>
63+
<th scope="row">{% trans "Default max utilization" %}</th>
5764
<td>{{ object.data.POWERFEED_DEFAULT_MAX_UTILIZATION }}</td>
5865
</tr>
5966
</table>
@@ -65,11 +72,11 @@ <h5 class="card-header">{% trans "IPAM" %}</h5>
6572
<div class="card-body">
6673
<table class="table table-hover attr-table">
6774
<tr>
68-
<th scope="row">{% trans "Enforce global unique" %}:</th>
75+
<th scope="row">{% trans "Enforce global unique" %}</th>
6976
<td>{{ object.data.ENFORCE_GLOBAL_UNIQUE }}</td>
7077
</tr>
7178
<tr>
72-
<th scope="row">{% trans "Prefer IPv4" %}:</th>
79+
<th scope="row">{% trans "Prefer IPv4" %}</th>
7380
<td>{{ object.data.PREFER_IPV4 }}</td>
7481
</tr>
7582
</table>
@@ -81,8 +88,8 @@ <h5 class="card-header">{% trans "Security" %}</h5>
8188
<div class="card-body">
8289
<table class="table table-hover attr-table">
8390
<tr>
84-
<th scope="row">{% trans "Allowed URL schemes" %}:</th>
85-
<td>{{ object.data.ALLOWED_URL_SCHEMES }}</td>
91+
<th scope="row">{% trans "Allowed URL schemes" %}</th>
92+
<td>{{ object.data.ALLOWED_URL_SCHEMES|join:", "|placeholder }}</td>
8693
</tr>
8794
</table>
8895
</div>
@@ -93,39 +100,35 @@ <h5 class="card-header">{% trans "Banners" %}</h5>
93100
<div class="card-body">
94101
<table class="table table-hover attr-table">
95102
<tr>
96-
<th scope="row">{% trans "Login banner" %}:</th>
103+
<th scope="row">{% trans "Login banner" %}</th>
97104
<td>{{ object.data.BANNER_LOGIN }}</td>
98105
</tr>
99106
<tr>
100-
<th scope="row">{% trans "Maintenance banner" %}:</th>
107+
<th scope="row">{% trans "Maintenance banner" %}</th>
101108
<td>{{ object.data.BANNER_MAINTENANCE }}</td>
102109
</tr>
103110
<tr>
104-
<th scope="row">{% trans "Top banner" %}:</th>
111+
<th scope="row">{% trans "Top banner" %}</th>
105112
<td>{{ object.data.BANNER_TOP }}</td>
106113
</tr>
107114
<tr>
108-
<th scope="row">{% trans "Bottom banner" %}:</th>
115+
<th scope="row">{% trans "Bottom banner" %}</th>
109116
<td>{{ object.data.BANNER_BOTTOM }}</td>
110117
</tr>
111118
</table>
112119
</div>
113120
</div>
114121

115-
116-
</div>
117-
<div class="col col-md-6">
118-
119122
<div class="card">
120123
<h5 class="card-header">{% trans "Pagination" %}</h5>
121124
<div class="card-body">
122125
<table class="table table-hover attr-table">
123126
<tr>
124-
<th scope="row">{% trans "Paginate count" %}:</th>
127+
<th scope="row">{% trans "Paginate count" %}</th>
125128
<td>{{ object.data.PAGINATE_COUNT }}</td>
126129
</tr>
127130
<tr>
128-
<th scope="row">{% trans "Max page size" %}:</th>
131+
<th scope="row">{% trans "Max page size" %}</th>
129132
<td>{{ object.data.MAX_PAGE_SIZE }}</td>
130133
</tr>
131134
</table>
@@ -137,8 +140,8 @@ <h5 class="card-header">{% trans "Validation" %}</h5>
137140
<div class="card-body">
138141
<table class="table table-hover attr-table">
139142
<tr>
140-
<th scope="row">{% trans "Custom validators" %}:</th>
141-
<td>{{ object.data.CUSTOM_VALIDATORS }}</td>
143+
<th scope="row">{% trans "Custom validators" %}</th>
144+
<td>{{ object.data.CUSTOM_VALIDATORS|placeholder }}</td>
142145
</tr>
143146
</table>
144147
</div>
@@ -149,8 +152,8 @@ <h5 class="card-header">{% trans "User Preferences" %}</h5>
149152
<div class="card-body">
150153
<table class="table table-hover attr-table">
151154
<tr>
152-
<th scope="row">{% trans "Default user preferences" %}:</th>
153-
<td>{{ object.data.DEFAULT_USER_PREFERENCES }}</td>
155+
<th scope="row">{% trans "Default user preferences" %}</th>
156+
<td>{{ object.data.DEFAULT_USER_PREFERENCES|placeholder }}</td>
154157
</tr>
155158
</table>
156159
</div>
@@ -161,38 +164,33 @@ <h5 class="card-header">{% trans "Miscellaneous" %}</h5>
161164
<div class="card-body">
162165
<table class="table table-hover attr-table">
163166
<tr>
164-
<th scope="row">{% trans "Maintenance mode" %}:</th>
167+
<th scope="row">{% trans "Maintenance mode" %}</th>
165168
<td>{{ object.data.MAINTENANCE_MODE }}</td>
166169
</tr>
167170
<tr>
168-
<th scope="row">{% trans "GraphQL enabled" %}:</th>
171+
<th scope="row">{% trans "GraphQL enabled" %}</th>
169172
<td>{{ object.data.GRAPHQL_ENABLED }}</td>
170173
</tr>
171174
<tr>
172-
<th scope="row">{% trans "Changelog retention" %}:</th>
175+
<th scope="row">{% trans "Changelog retention" %}</th>
173176
<td>{{ object.data.CHANGELOG_RETENTION }}</td>
174177
</tr>
175178
<tr>
176-
<th scope="row">{% trans "Job retention" %}:</th>
179+
<th scope="row">{% trans "Job retention" %}</th>
177180
<td>{{ object.data.JOB_RETENTION }}</td>
178181
</tr>
179182
<tr>
180-
<th scope="row">{% trans "Maps URL" %}:</th>
183+
<th scope="row">{% trans "Maps URL" %}</th>
181184
<td>{{ object.data.MAPS_URL }}</td>
182185
</tr>
183186
</table>
184187
</div>
185188
</div>
186189

187190
<div class="card">
188-
<h5 class="card-header">{% trans "Config Revision" %}</h5>
191+
<h5 class="card-header">{% trans "Comment" %}</h5>
189192
<div class="card-body">
190-
<table class="table table-hover attr-table">
191-
<tr>
192-
<th scope="row">{% trans "Comment" %}:</th>
193-
<td>{{ object.comment }}</td>
194-
</tr>
195-
</table>
193+
{{ object.comment|placeholder }}
196194
</div>
197195
</div>
198196

0 commit comments

Comments
 (0)