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:
@ -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'),
|
||||||
|
|
||||||
)
|
)
|
||||||
|
@ -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()
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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'),
|
||||||
|
@ -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'),
|
||||||
|
@ -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>
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user