1
0
mirror of https://github.com/netbox-community/netbox.git synced 2024-05-10 07:54:54 +00:00

#12591: Add a dedicated view for the active config revision

This commit is contained in:
Jeremy Stretch
2023-08-30 11:13:56 -04:00
parent 210d7bb573
commit eb9a804914
7 changed files with 66 additions and 45 deletions

View File

@ -25,4 +25,7 @@ urlpatterns = (
path('jobs/<int:pk>/', views.JobView.as_view(), name='job'), path('jobs/<int:pk>/', views.JobView.as_view(), name='job'),
path('jobs/<int:pk>/delete/', views.JobDeleteView.as_view(), name='job_delete'), path('jobs/<int:pk>/delete/', views.JobDeleteView.as_view(), name='job_delete'),
# Configuration
path('config/', views.ConfigView.as_view(), name='config'),
) )

View File

@ -1,6 +1,7 @@
from django.contrib import messages from django.contrib import messages
from django.shortcuts import get_object_or_404, redirect from django.shortcuts import get_object_or_404, redirect
from extras.models import ConfigRevision
from netbox.views import generic from netbox.views import generic
from netbox.views.generic.base import BaseObjectView from netbox.views.generic.base import BaseObjectView
from utilities.utils import count_related from utilities.utils import count_related
@ -141,3 +142,14 @@ class JobBulkDeleteView(generic.BulkDeleteView):
queryset = Job.objects.all() queryset = Job.objects.all()
filterset = filtersets.JobFilterSet filterset = filtersets.JobFilterSet
table = tables.JobTable table = tables.JobTable
#
# Config Revisions
#
class ConfigView(generic.ObjectView):
queryset = ConfigRevision.objects.all()
def get_object(self, **kwargs):
return self.queryset.first()

View File

@ -490,7 +490,9 @@ class ConfigRevisionForm(BootstrapMixin, forms.ModelForm, metaclass=ConfigFormMe
(_('Pagination'), ('PAGINATE_COUNT', 'MAX_PAGE_SIZE')), (_('Pagination'), ('PAGINATE_COUNT', 'MAX_PAGE_SIZE')),
(_('Validation'), ('CUSTOM_VALIDATORS',)), (_('Validation'), ('CUSTOM_VALIDATORS',)),
(_('User Preferences'), ('DEFAULT_USER_PREFERENCES',)), (_('User Preferences'), ('DEFAULT_USER_PREFERENCES',)),
(_('Miscellaneous'), ('MAINTENANCE_MODE', 'GRAPHQL_ENABLED', 'CHANGELOG_RETENTION', 'JOB_RETENTION', 'MAPS_URL')), (_('Miscellaneous'), (
'MAINTENANCE_MODE', 'GRAPHQL_ENABLED', 'CHANGELOG_RETENTION', 'JOB_RETENTION', 'MAPS_URL',
)),
(_('Config Revision'), ('comment',)) (_('Config Revision'), ('comment',))
) )
@ -524,6 +526,8 @@ class ConfigRevisionForm(BootstrapMixin, forms.ModelForm, metaclass=ConfigFormMe
elif value == param.default: elif value == param.default:
help_text += _(' (default)') help_text += _(' (default)')
self.fields[param.name].help_text = help_text self.fields[param.name].help_text = help_text
if type(value) in (tuple, list):
value = ', '.join(value)
self.fields[param.name].initial = value self.fields[param.name].initial = value
if is_static: if is_static:
self.fields[param.name].disabled = True self.fields[param.name].disabled = True

View File

@ -1,7 +1,6 @@
import json import json
import urllib.parse import urllib.parse
from django.contrib import admin
from django.conf import settings from django.conf import settings
from django.contrib.contenttypes.fields import GenericForeignKey from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
@ -12,7 +11,7 @@ from django.http import HttpResponse
from django.urls import reverse from django.urls import reverse
from django.utils import timezone from django.utils import timezone
from django.utils.formats import date_format from django.utils.formats import date_format
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext, gettext_lazy as _
from rest_framework.utils.encoders import JSONEncoder from rest_framework.utils.encoders import JSONEncoder
from extras.choices import * from extras.choices import *
@ -724,7 +723,9 @@ class ConfigRevision(models.Model):
verbose_name_plural = _('config revisions') verbose_name_plural = _('config revisions')
def __str__(self): def __str__(self):
return f'Config revision #{self.pk} ({self.created})' if self.is_active:
return gettext('Current configuration')
return gettext('Config revision #{id}').format(id=self.pk)
def __getattr__(self, item): def __getattr__(self, item):
if item in self.data: if item in self.data:
@ -742,6 +743,6 @@ class ConfigRevision(models.Model):
cache.set('config_version', self.pk, None) cache.set('config_version', self.pk, None)
activate.alters_data = True activate.alters_data = True
@admin.display(boolean=True) @property
def is_active(self): def is_active(self):
return cache.get('config_version') == self.pk return cache.get('config_version') == self.pk

View File

@ -102,7 +102,6 @@ PARAMS = (
description=_("Default voltage for powerfeeds"), description=_("Default voltage for powerfeeds"),
field=forms.IntegerField field=forms.IntegerField
), ),
ConfigParam( ConfigParam(
name='POWERFEED_DEFAULT_AMPERAGE', name='POWERFEED_DEFAULT_AMPERAGE',
label=_('Powerfeed amperage'), label=_('Powerfeed amperage'),
@ -110,7 +109,6 @@ PARAMS = (
description=_("Default amperage for powerfeeds"), description=_("Default amperage for powerfeeds"),
field=forms.IntegerField field=forms.IntegerField
), ),
ConfigParam( ConfigParam(
name='POWERFEED_DEFAULT_MAX_UTILIZATION', name='POWERFEED_DEFAULT_MAX_UTILIZATION',
label=_('Powerfeed max utilization'), label=_('Powerfeed max utilization'),

View File

@ -406,6 +406,11 @@ ADMIN_MENU = Menu(
MenuGroup( MenuGroup(
label=_('Configuration'), label=_('Configuration'),
items=( items=(
MenuItem(
link='core:config',
link_text=_('Current Config'),
permissions=['extras.view_configrevision']
),
MenuItem( MenuItem(
link='extras:configrevision_list', link='extras:configrevision_list',
link_text=_('Config Revisions'), link_text=_('Config Revisions'),

View File

@ -14,6 +14,13 @@
<div class="controls"> <div class="controls">
<div class="control-group"> <div class="control-group">
{% plugin_buttons object %} {% plugin_buttons object %}
{% if object.is_active and perms.extras.add_configrevision %}
{% url 'extras:configrevision_add' as edit_url %}
{% include "buttons/edit.html" with url=edit_url %}
{% endif %}
{% if not object.is_active and perms.extras.delete_configrevision %}
{% delete_button object %}
{% endif %}
</div> </div>
<div class="control-group"> <div class="control-group">
{% custom_links object %} {% custom_links object %}
@ -23,17 +30,17 @@
{% block content %} {% block content %}
<div class="row"> <div class="row">
<div class="col col-md-6"> <div class="col col-md-12">
<div class="card"> <div class="card">
<h5 class="card-header">{% trans "Rack Elevation" %}</h5> <h5 class="card-header">{% trans "Rack Elevations" %}</h5>
<div class="card-body"> <div class="card-body">
<table class="table table-hover attr-table"> <table class="table table-hover attr-table">
<tr> <tr>
<th scope="row">{% trans "Rack elevation default unit height" %}:</th> <th scope="row">{% trans "Default unit height" %}</th>
<td>{{ object.data.RACK_ELEVATION_DEFAULT_UNIT_HEIGHT }}</td> <td>{{ object.data.RACK_ELEVATION_DEFAULT_UNIT_HEIGHT }}</td>
</tr> </tr>
<tr> <tr>
<th scope="row">{% trans "Rack elevation default unit width" %}:</th> <th scope="row">{% trans "Default unit width" %}</th>
<td>{{ object.data.RACK_ELEVATION_DEFAULT_UNIT_WIDTH }}</td> <td>{{ object.data.RACK_ELEVATION_DEFAULT_UNIT_WIDTH }}</td>
</tr> </tr>
</table> </table>
@ -41,19 +48,19 @@
</div> </div>
<div class="card"> <div class="card">
<h5 class="card-header">{% trans "Power" %}</h5> <h5 class="card-header">{% trans "Power Feeds" %}</h5>
<div class="card-body"> <div class="card-body">
<table class="table table-hover attr-table"> <table class="table table-hover attr-table">
<tr> <tr>
<th scope="row">{% trans "Powerfeed default voltage" %}:</th> <th scope="row">{% trans "Default voltage" %}</th>
<td>{{ object.data.POWERFEED_DEFAULT_VOLTAGE }}</td> <td>{{ object.data.POWERFEED_DEFAULT_VOLTAGE }}</td>
</tr> </tr>
<tr> <tr>
<th scope="row">{% trans "Powerfeed default amperage" %}:</th> <th scope="row">{% trans "Default amperage" %}</th>
<td>{{ object.data.POWERFEED_DEFAULT_AMPERAGE }}</td> <td>{{ object.data.POWERFEED_DEFAULT_AMPERAGE }}</td>
</tr> </tr>
<tr> <tr>
<th scope="row">{% trans "Powerfeed default max utilization" %}:</th> <th scope="row">{% trans "Default max utilization" %}</th>
<td>{{ object.data.POWERFEED_DEFAULT_MAX_UTILIZATION }}</td> <td>{{ object.data.POWERFEED_DEFAULT_MAX_UTILIZATION }}</td>
</tr> </tr>
</table> </table>
@ -65,11 +72,11 @@
<div class="card-body"> <div class="card-body">
<table class="table table-hover attr-table"> <table class="table table-hover attr-table">
<tr> <tr>
<th scope="row">{% trans "Enforce global unique" %}:</th> <th scope="row">{% trans "Enforce global unique" %}</th>
<td>{{ object.data.ENFORCE_GLOBAL_UNIQUE }}</td> <td>{{ object.data.ENFORCE_GLOBAL_UNIQUE }}</td>
</tr> </tr>
<tr> <tr>
<th scope="row">{% trans "Prefer IPv4" %}:</th> <th scope="row">{% trans "Prefer IPv4" %}</th>
<td>{{ object.data.PREFER_IPV4 }}</td> <td>{{ object.data.PREFER_IPV4 }}</td>
</tr> </tr>
</table> </table>
@ -81,8 +88,8 @@
<div class="card-body"> <div class="card-body">
<table class="table table-hover attr-table"> <table class="table table-hover attr-table">
<tr> <tr>
<th scope="row">{% trans "Allowed URL schemes" %}:</th> <th scope="row">{% trans "Allowed URL schemes" %}</th>
<td>{{ object.data.ALLOWED_URL_SCHEMES }}</td> <td>{{ object.data.ALLOWED_URL_SCHEMES|join:", "|placeholder }}</td>
</tr> </tr>
</table> </table>
</div> </div>
@ -93,39 +100,35 @@
<div class="card-body"> <div class="card-body">
<table class="table table-hover attr-table"> <table class="table table-hover attr-table">
<tr> <tr>
<th scope="row">{% trans "Login banner" %}:</th> <th scope="row">{% trans "Login banner" %}</th>
<td>{{ object.data.BANNER_LOGIN }}</td> <td>{{ object.data.BANNER_LOGIN }}</td>
</tr> </tr>
<tr> <tr>
<th scope="row">{% trans "Maintenance banner" %}:</th> <th scope="row">{% trans "Maintenance banner" %}</th>
<td>{{ object.data.BANNER_MAINTENANCE }}</td> <td>{{ object.data.BANNER_MAINTENANCE }}</td>
</tr> </tr>
<tr> <tr>
<th scope="row">{% trans "Top banner" %}:</th> <th scope="row">{% trans "Top banner" %}</th>
<td>{{ object.data.BANNER_TOP }}</td> <td>{{ object.data.BANNER_TOP }}</td>
</tr> </tr>
<tr> <tr>
<th scope="row">{% trans "Bottom banner" %}:</th> <th scope="row">{% trans "Bottom banner" %}</th>
<td>{{ object.data.BANNER_BOTTOM }}</td> <td>{{ object.data.BANNER_BOTTOM }}</td>
</tr> </tr>
</table> </table>
</div> </div>
</div> </div>
</div>
<div class="col col-md-6">
<div class="card"> <div class="card">
<h5 class="card-header">{% trans "Pagination" %}</h5> <h5 class="card-header">{% trans "Pagination" %}</h5>
<div class="card-body"> <div class="card-body">
<table class="table table-hover attr-table"> <table class="table table-hover attr-table">
<tr> <tr>
<th scope="row">{% trans "Paginate count" %}:</th> <th scope="row">{% trans "Paginate count" %}</th>
<td>{{ object.data.PAGINATE_COUNT }}</td> <td>{{ object.data.PAGINATE_COUNT }}</td>
</tr> </tr>
<tr> <tr>
<th scope="row">{% trans "Max page size" %}:</th> <th scope="row">{% trans "Max page size" %}</th>
<td>{{ object.data.MAX_PAGE_SIZE }}</td> <td>{{ object.data.MAX_PAGE_SIZE }}</td>
</tr> </tr>
</table> </table>
@ -137,8 +140,8 @@
<div class="card-body"> <div class="card-body">
<table class="table table-hover attr-table"> <table class="table table-hover attr-table">
<tr> <tr>
<th scope="row">{% trans "Custom validators" %}:</th> <th scope="row">{% trans "Custom validators" %}</th>
<td>{{ object.data.CUSTOM_VALIDATORS }}</td> <td>{{ object.data.CUSTOM_VALIDATORS|placeholder }}</td>
</tr> </tr>
</table> </table>
</div> </div>
@ -149,8 +152,8 @@
<div class="card-body"> <div class="card-body">
<table class="table table-hover attr-table"> <table class="table table-hover attr-table">
<tr> <tr>
<th scope="row">{% trans "Default user preferences" %}:</th> <th scope="row">{% trans "Default user preferences" %}</th>
<td>{{ object.data.DEFAULT_USER_PREFERENCES }}</td> <td>{{ object.data.DEFAULT_USER_PREFERENCES|placeholder }}</td>
</tr> </tr>
</table> </table>
</div> </div>
@ -161,23 +164,23 @@
<div class="card-body"> <div class="card-body">
<table class="table table-hover attr-table"> <table class="table table-hover attr-table">
<tr> <tr>
<th scope="row">{% trans "Maintenance mode" %}:</th> <th scope="row">{% trans "Maintenance mode" %}</th>
<td>{{ object.data.MAINTENANCE_MODE }}</td> <td>{{ object.data.MAINTENANCE_MODE }}</td>
</tr> </tr>
<tr> <tr>
<th scope="row">{% trans "GraphQL enabled" %}:</th> <th scope="row">{% trans "GraphQL enabled" %}</th>
<td>{{ object.data.GRAPHQL_ENABLED }}</td> <td>{{ object.data.GRAPHQL_ENABLED }}</td>
</tr> </tr>
<tr> <tr>
<th scope="row">{% trans "Changelog retention" %}:</th> <th scope="row">{% trans "Changelog retention" %}</th>
<td>{{ object.data.CHANGELOG_RETENTION }}</td> <td>{{ object.data.CHANGELOG_RETENTION }}</td>
</tr> </tr>
<tr> <tr>
<th scope="row">{% trans "Job retention" %}:</th> <th scope="row">{% trans "Job retention" %}</th>
<td>{{ object.data.JOB_RETENTION }}</td> <td>{{ object.data.JOB_RETENTION }}</td>
</tr> </tr>
<tr> <tr>
<th scope="row">{% trans "Maps URL" %}:</th> <th scope="row">{% trans "Maps URL" %}</th>
<td>{{ object.data.MAPS_URL }}</td> <td>{{ object.data.MAPS_URL }}</td>
</tr> </tr>
</table> </table>
@ -185,14 +188,9 @@
</div> </div>
<div class="card"> <div class="card">
<h5 class="card-header">{% trans "Config Revision" %}</h5> <h5 class="card-header">{% trans "Comment" %}</h5>
<div class="card-body"> <div class="card-body">
<table class="table table-hover attr-table"> {{ object.comment|placeholder }}
<tr>
<th scope="row">{% trans "Comment" %}:</th>
<td>{{ object.comment }}</td>
</tr>
</table>
</div> </div>
</div> </div>