Merge branch 'develop' into 16274-dark-mode-highlight

This commit is contained in:
Louis Jarasius 2024-06-05 07:37:59 +10:00
commit f4dc84f234
No known key found for this signature in database
22 changed files with 258 additions and 214 deletions

View File

@ -12,7 +12,7 @@ jobs:
auto-assign: auto-assign:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: pozil/auto-assign-issue@v1 - uses: pozil/auto-assign-issue@v2
if: "contains(github.event.issue.labels.*.name, 'status: needs triage')" if: "contains(github.event.issue.labels.*.name, 'status: needs triage')"
with: with:
# Weighted assignments # Weighted assignments

View File

@ -45,12 +45,12 @@ jobs:
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }} - name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4 uses: actions/setup-python@v5
with: with:
python-version: ${{ matrix.python-version }} python-version: ${{ matrix.python-version }}
- name: Use Node.js ${{ matrix.node-version }} - name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3 uses: actions/setup-node@v4
with: with:
node-version: ${{ matrix.node-version }} node-version: ${{ matrix.node-version }}
@ -58,7 +58,7 @@ jobs:
run: npm install -g yarn run: npm install -g yarn
- name: Setup Node.js with Yarn Caching - name: Setup Node.js with Yarn Caching
uses: actions/setup-node@v3 uses: actions/setup-node@v4
with: with:
node-version: ${{ matrix.node-version }} node-version: ${{ matrix.node-version }}
cache: yarn cache: yarn

View File

@ -22,7 +22,7 @@ jobs:
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Set up Python - name: Set up Python
uses: actions/setup-python@v4 uses: actions/setup-python@v5
with: with:
python-version: 3.11 python-version: 3.11

View File

@ -2,6 +2,18 @@
## v4.0.4 (FUTURE) ## v4.0.4 (FUTURE)
### Enhancements
* [#14810](https://github.com/netbox-community/netbox/issues/14810) - Enable contact assignment for services
* [#15489](https://github.com/netbox-community/netbox/issues/15489) - Add 1000Base-TX interface type
* [#16290](https://github.com/netbox-community/netbox/issues/16290) - Capture entire object in changelog data (but continue to display only non-internal attributes)
### Bug Fixes
* [#13422](https://github.com/netbox-community/netbox/issues/13422) - Rebuild MPTT trees for applicable models after merging staged changes
* [#16202](https://github.com/netbox-community/netbox/issues/16202) - Fix site map button URL for certain localizations
* [#16286](https://github.com/netbox-community/netbox/issues/16286) - Fix global search support for provider accounts
--- ---
## v4.0.3 (2024-05-22) ## v4.0.3 (2024-05-22)

View File

@ -355,11 +355,11 @@ class CableTermination(ChangeLoggedModel):
super().save(*args, **kwargs) super().save(*args, **kwargs)
# Set the cable on the terminating object # Set the cable on the terminating object
termination_model = self.termination._meta.model termination = self.termination._meta.model.objects.get(pk=self.termination_id)
termination_model.objects.filter(pk=self.termination_id).update( termination.snapshot()
cable=self.cable, termination.cable = self.cable
cable_end=self.cable_end termination.cable_end = self.cable_end
) termination.save()
def delete(self, *args, **kwargs): def delete(self, *args, **kwargs):

View File

@ -43,14 +43,6 @@ MODULEBAY_STATUS = """
""" """
def get_cabletermination_row_class(record):
if record.mark_connected:
return 'success'
elif record.cable:
return record.cable.get_status_color()
return ''
# #
# Device roles # Device roles
# #
@ -339,6 +331,14 @@ class CableTerminationTable(NetBoxTable):
verbose_name=_('Mark Connected'), verbose_name=_('Mark Connected'),
) )
class Meta:
row_attrs = {
'data-name': lambda record: record.name,
'data-mark-connected': lambda record: "true" if record.mark_connected else "false",
'data-cable-status': lambda record: record.cable.status if record.cable else "",
'data-type': lambda record: record.type
}
def value_link_peer(self, value): def value_link_peer(self, value):
return ', '.join([ return ', '.join([
f"{termination.parent_object} > {termination}" for termination in value f"{termination.parent_object} > {termination}" for termination in value
@ -386,16 +386,13 @@ class DeviceConsolePortTable(ConsolePortTable):
extra_buttons=CONSOLEPORT_BUTTONS extra_buttons=CONSOLEPORT_BUTTONS
) )
class Meta(DeviceComponentTable.Meta): class Meta(CableTerminationTable.Meta, DeviceComponentTable.Meta):
model = models.ConsolePort model = models.ConsolePort
fields = ( fields = (
'pk', 'id', 'name', 'module_bay', 'module', 'label', 'type', 'speed', 'description', 'mark_connected', 'pk', 'id', 'name', 'module_bay', 'module', 'label', 'type', 'speed', 'description', 'mark_connected',
'cable', 'cable_color', 'link_peer', 'connection', 'tags', 'actions' 'cable', 'cable_color', 'link_peer', 'connection', 'tags', 'actions'
) )
default_columns = ('pk', 'name', 'label', 'type', 'speed', 'description', 'cable', 'connection') default_columns = ('pk', 'name', 'label', 'type', 'speed', 'description', 'cable', 'connection')
row_attrs = {
'class': get_cabletermination_row_class
}
class ConsoleServerPortTable(ModularDeviceComponentTable, PathEndpointTable): class ConsoleServerPortTable(ModularDeviceComponentTable, PathEndpointTable):
@ -431,16 +428,13 @@ class DeviceConsoleServerPortTable(ConsoleServerPortTable):
extra_buttons=CONSOLESERVERPORT_BUTTONS extra_buttons=CONSOLESERVERPORT_BUTTONS
) )
class Meta(DeviceComponentTable.Meta): class Meta(CableTerminationTable.Meta, DeviceComponentTable.Meta):
model = models.ConsoleServerPort model = models.ConsoleServerPort
fields = ( fields = (
'pk', 'id', 'name', 'module_bay', 'module', 'label', 'type', 'speed', 'description', 'mark_connected', 'pk', 'id', 'name', 'module_bay', 'module', 'label', 'type', 'speed', 'description', 'mark_connected',
'cable', 'cable_color', 'link_peer', 'connection', 'tags', 'actions', 'cable', 'cable_color', 'link_peer', 'connection', 'tags', 'actions',
) )
default_columns = ('pk', 'name', 'label', 'type', 'speed', 'description', 'cable', 'connection') default_columns = ('pk', 'name', 'label', 'type', 'speed', 'description', 'cable', 'connection')
row_attrs = {
'class': get_cabletermination_row_class
}
class PowerPortTable(ModularDeviceComponentTable, PathEndpointTable): class PowerPortTable(ModularDeviceComponentTable, PathEndpointTable):
@ -483,7 +477,7 @@ class DevicePowerPortTable(PowerPortTable):
extra_buttons=POWERPORT_BUTTONS extra_buttons=POWERPORT_BUTTONS
) )
class Meta(DeviceComponentTable.Meta): class Meta(CableTerminationTable.Meta, DeviceComponentTable.Meta):
model = models.PowerPort model = models.PowerPort
fields = ( fields = (
'pk', 'id', 'name', 'module_bay', 'module', 'label', 'type', 'maximum_draw', 'allocated_draw', 'pk', 'id', 'name', 'module_bay', 'module', 'label', 'type', 'maximum_draw', 'allocated_draw',
@ -492,9 +486,6 @@ class DevicePowerPortTable(PowerPortTable):
default_columns = ( default_columns = (
'pk', 'name', 'label', 'type', 'maximum_draw', 'allocated_draw', 'description', 'cable', 'connection', 'pk', 'name', 'label', 'type', 'maximum_draw', 'allocated_draw', 'description', 'cable', 'connection',
) )
row_attrs = {
'class': get_cabletermination_row_class
}
class PowerOutletTable(ModularDeviceComponentTable, PathEndpointTable): class PowerOutletTable(ModularDeviceComponentTable, PathEndpointTable):
@ -534,7 +525,7 @@ class DevicePowerOutletTable(PowerOutletTable):
extra_buttons=POWEROUTLET_BUTTONS extra_buttons=POWEROUTLET_BUTTONS
) )
class Meta(DeviceComponentTable.Meta): class Meta(CableTerminationTable.Meta, DeviceComponentTable.Meta):
model = models.PowerOutlet model = models.PowerOutlet
fields = ( fields = (
'pk', 'id', 'name', 'module_bay', 'module', 'label', 'type', 'power_port', 'feed_leg', 'description', 'pk', 'id', 'name', 'module_bay', 'module', 'label', 'type', 'power_port', 'feed_leg', 'description',
@ -543,9 +534,6 @@ class DevicePowerOutletTable(PowerOutletTable):
default_columns = ( default_columns = (
'pk', 'name', 'label', 'type', 'power_port', 'feed_leg', 'description', 'cable', 'connection', 'pk', 'name', 'label', 'type', 'power_port', 'feed_leg', 'description', 'cable', 'connection',
) )
row_attrs = {
'class': get_cabletermination_row_class
}
class BaseInterfaceTable(NetBoxTable): class BaseInterfaceTable(NetBoxTable):
@ -733,7 +721,7 @@ class DeviceFrontPortTable(FrontPortTable):
extra_buttons=FRONTPORT_BUTTONS extra_buttons=FRONTPORT_BUTTONS
) )
class Meta(DeviceComponentTable.Meta): class Meta(CableTerminationTable.Meta, DeviceComponentTable.Meta):
model = models.FrontPort model = models.FrontPort
fields = ( fields = (
'pk', 'id', 'name', 'module_bay', 'module', 'label', 'type', 'rear_port', 'rear_port_position', 'pk', 'id', 'name', 'module_bay', 'module', 'label', 'type', 'rear_port', 'rear_port_position',
@ -742,9 +730,6 @@ class DeviceFrontPortTable(FrontPortTable):
default_columns = ( default_columns = (
'pk', 'name', 'label', 'type', 'rear_port', 'rear_port_position', 'description', 'cable', 'link_peer', 'pk', 'name', 'label', 'type', 'rear_port', 'rear_port_position', 'description', 'cable', 'link_peer',
) )
row_attrs = {
'class': get_cabletermination_row_class
}
class RearPortTable(ModularDeviceComponentTable, CableTerminationTable): class RearPortTable(ModularDeviceComponentTable, CableTerminationTable):
@ -783,7 +768,7 @@ class DeviceRearPortTable(RearPortTable):
extra_buttons=REARPORT_BUTTONS extra_buttons=REARPORT_BUTTONS
) )
class Meta(DeviceComponentTable.Meta): class Meta(CableTerminationTable.Meta, DeviceComponentTable.Meta):
model = models.RearPort model = models.RearPort
fields = ( fields = (
'pk', 'id', 'name', 'module_bay', 'module', 'label', 'type', 'positions', 'description', 'mark_connected', 'pk', 'id', 'name', 'module_bay', 'module', 'label', 'type', 'positions', 'description', 'mark_connected',
@ -792,9 +777,6 @@ class DeviceRearPortTable(RearPortTable):
default_columns = ( default_columns = (
'pk', 'name', 'label', 'type', 'positions', 'description', 'cable', 'link_peer', 'pk', 'name', 'label', 'type', 'positions', 'description', 'cable', 'link_peer',
) )
row_attrs = {
'class': get_cabletermination_row_class
}
class DeviceBayTable(DeviceComponentTable): class DeviceBayTable(DeviceComponentTable):

View File

@ -13,13 +13,14 @@ def event_tracking(request):
:param request: WSGIRequest object with a unique `id` set :param request: WSGIRequest object with a unique `id` set
""" """
current_request.set(request) current_request.set(request)
events_queue.set([]) events_queue.set({})
yield yield
# Flush queued webhooks to RQ # Flush queued webhooks to RQ
flush_events(events_queue.get()) if events := list(events_queue.get().values()):
flush_events(events)
# Clear context vars # Clear context vars
current_request.set(None) current_request.set(None)
events_queue.set([]) events_queue.set({})

View File

@ -265,6 +265,7 @@ class ObjectListWidget(DashboardWidget):
parameters = self.config.get('url_params') or {} parameters = self.config.get('url_params') or {}
if page_size := self.config.get('page_size'): if page_size := self.config.get('page_size'):
parameters['per_page'] = page_size parameters['per_page'] = page_size
parameters['embedded'] = True
if parameters: if parameters:
try: try:

View File

@ -58,15 +58,21 @@ def enqueue_object(queue, instance, user, request_id, action):
if model_name not in registry['model_features']['event_rules'].get(app_label, []): if model_name not in registry['model_features']['event_rules'].get(app_label, []):
return return
queue.append({ assert instance.pk is not None
'content_type': ContentType.objects.get_for_model(instance), key = f'{app_label}.{model_name}:{instance.pk}'
'object_id': instance.pk, if key in queue:
'event': action, queue[key]['data'] = serialize_for_event(instance)
'data': serialize_for_event(instance), queue[key]['snapshots']['postchange'] = get_snapshots(instance, action)['postchange']
'snapshots': get_snapshots(instance, action), else:
'username': user.username, queue[key] = {
'request_id': request_id 'content_type': ContentType.objects.get_for_model(instance),
}) 'object_id': instance.pk,
'event': action,
'data': serialize_for_event(instance),
'snapshots': get_snapshots(instance, action),
'username': user.username,
'request_id': request_id
}
def process_event_rules(event_rules, model_name, event, data, username=None, snapshots=None, request_id=None): def process_event_rules(event_rules, model_name, event, data, username=None, snapshots=None, request_id=None):
@ -163,14 +169,14 @@ def process_event_queue(events):
) )
def flush_events(queue): def flush_events(events):
""" """
Flush a list of object representation to RQ for webhook processing. Flush a list of object representations to RQ for event processing.
""" """
if queue: if events:
for name in settings.EVENTS_PIPELINE: for name in settings.EVENTS_PIPELINE:
try: try:
func = import_string(name) func = import_string(name)
func(queue) func(events)
except Exception as e: except Exception as e:
logger.error(_("Cannot import events pipeline {name} error: {error}").format(name=name, error=e)) logger.error(_("Cannot import events pipeline {name} error: {error}").format(name=name, error=e))

View File

@ -464,13 +464,10 @@ class JournalEntryFilterForm(NetBoxModelFilterSetForm):
required=False, required=False,
label=_('User') label=_('User')
) )
assigned_object_type_id = DynamicModelMultipleChoiceField( assigned_object_type_id = ContentTypeMultipleChoiceField(
queryset=ObjectType.objects.all(), queryset=ObjectType.objects.with_feature('journaling'),
required=False, required=False,
label=_('Object Type'), label=_('Object Type'),
widget=APISelectMultiple(
api_url='/api/extras/content-types/',
)
) )
kind = forms.ChoiceField( kind = forms.ChoiceField(
label=_('Kind'), label=_('Kind'),
@ -507,11 +504,8 @@ class ObjectChangeFilterForm(SavedFiltersMixin, FilterForm):
required=False, required=False,
label=_('User') label=_('User')
) )
changed_object_type_id = DynamicModelMultipleChoiceField( changed_object_type_id = ContentTypeMultipleChoiceField(
queryset=ObjectType.objects.all(), queryset=ObjectType.objects.with_feature('change_logging'),
required=False, required=False,
label=_('Object Type'), label=_('Object Type'),
widget=APISelectMultiple(
api_url='/api/extras/content-types/',
)
) )

View File

@ -4,6 +4,7 @@ from django.contrib.auth import get_user_model
from django.contrib.contenttypes.fields import GenericForeignKey from django.contrib.contenttypes.fields import GenericForeignKey
from django.db import models, transaction from django.db import models, transaction
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from mptt.models import MPTTModel
from extras.choices import ChangeActionChoices from extras.choices import ChangeActionChoices
from netbox.models import ChangeLoggedModel from netbox.models import ChangeLoggedModel
@ -124,6 +125,11 @@ class StagedChange(CustomValidationMixin, EventRulesMixin, models.Model):
instance = self.model.objects.get(pk=self.object_id) instance = self.model.objects.get(pk=self.object_id)
logger.info(f'Deleting {self.model._meta.verbose_name} {instance}') logger.info(f'Deleting {self.model._meta.verbose_name} {instance}')
instance.delete() instance.delete()
# Rebuild the MPTT tree where applicable
if issubclass(self.model, MPTTModel):
self.model.objects.rebuild()
apply.alters_data = True apply.alters_data = True
def get_action_color(self): def get_action_color(self):

View File

@ -55,18 +55,6 @@ def run_validators(instance, validators):
clear_events = Signal() clear_events = Signal()
def is_same_object(instance, webhook_data, request_id):
"""
Compare the given instance to the most recent queued webhook object, returning True
if they match. This check is used to avoid creating duplicate webhook entries.
"""
return (
ContentType.objects.get_for_model(instance) == webhook_data['content_type'] and
instance.pk == webhook_data['object_id'] and
request_id == webhook_data['request_id']
)
@receiver((post_save, m2m_changed)) @receiver((post_save, m2m_changed))
def handle_changed_object(sender, instance, **kwargs): def handle_changed_object(sender, instance, **kwargs):
""" """
@ -112,14 +100,13 @@ def handle_changed_object(sender, instance, **kwargs):
objectchange.request_id = request.id objectchange.request_id = request.id
objectchange.save() objectchange.save()
# If this is an M2M change, update the previously queued webhook (from post_save) # Ensure that we're working with fresh M2M assignments
if m2m_changed:
instance.refresh_from_db()
# Enqueue the object for event processing
queue = events_queue.get() queue = events_queue.get()
if m2m_changed and queue and is_same_object(instance, queue[-1], request.id): enqueue_object(queue, instance, request.user, request.id, action)
instance.refresh_from_db() # Ensure that we're working with fresh M2M assignments
queue[-1]['data'] = serialize_for_event(instance)
queue[-1]['snapshots']['postchange'] = get_snapshots(instance, action)['postchange']
else:
enqueue_object(queue, instance, request.user, request.id, action)
events_queue.set(queue) events_queue.set(queue)
# Increment metric counters # Increment metric counters
@ -179,7 +166,7 @@ def handle_deleted_object(sender, instance, **kwargs):
obj.snapshot() # Ensure the change record includes the "before" state obj.snapshot() # Ensure the change record includes the "before" state
getattr(obj, related_field_name).remove(instance) getattr(obj, related_field_name).remove(instance)
# Enqueue webhooks # Enqueue the object for event processing
queue = events_queue.get() queue = events_queue.get()
enqueue_object(queue, instance, request.user, request.id, ObjectChangeActionChoices.ACTION_DELETE) enqueue_object(queue, instance, request.user, request.id, ObjectChangeActionChoices.ACTION_DELETE)
events_queue.set(queue) events_queue.set(queue)
@ -195,7 +182,7 @@ def clear_events_queue(sender, **kwargs):
""" """
logger = logging.getLogger('events') logger = logging.getLogger('events')
logger.info(f"Clearing {len(events_queue.get())} queued events ({sender})") logger.info(f"Clearing {len(events_queue.get())} queued events ({sender})")
events_queue.set([]) events_queue.set({})
# #

View File

@ -4,6 +4,7 @@ from unittest.mock import patch
import django_rq import django_rq
from django.http import HttpResponse from django.http import HttpResponse
from django.test import RequestFactory
from django.urls import reverse from django.urls import reverse
from requests import Session from requests import Session
from rest_framework import status from rest_framework import status
@ -12,6 +13,7 @@ from core.models import ObjectType
from dcim.choices import SiteStatusChoices from dcim.choices import SiteStatusChoices
from dcim.models import Site from dcim.models import Site
from extras.choices import EventRuleActionChoices, ObjectChangeActionChoices from extras.choices import EventRuleActionChoices, ObjectChangeActionChoices
from extras.context_managers import event_tracking
from extras.events import enqueue_object, flush_events, serialize_for_event from extras.events import enqueue_object, flush_events, serialize_for_event
from extras.models import EventRule, Tag, Webhook from extras.models import EventRule, Tag, Webhook
from extras.webhooks import generate_signature, send_webhook from extras.webhooks import generate_signature, send_webhook
@ -360,7 +362,7 @@ class EventRuleTest(APITestCase):
return HttpResponse() return HttpResponse()
# Enqueue a webhook for processing # Enqueue a webhook for processing
webhooks_queue = [] webhooks_queue = {}
site = Site.objects.create(name='Site 1', slug='site-1') site = Site.objects.create(name='Site 1', slug='site-1')
enqueue_object( enqueue_object(
webhooks_queue, webhooks_queue,
@ -369,7 +371,7 @@ class EventRuleTest(APITestCase):
request_id=request_id, request_id=request_id,
action=ObjectChangeActionChoices.ACTION_CREATE action=ObjectChangeActionChoices.ACTION_CREATE
) )
flush_events(webhooks_queue) flush_events(list(webhooks_queue.values()))
# Retrieve the job from queue # Retrieve the job from queue
job = self.queue.jobs[0] job = self.queue.jobs[0]
@ -377,3 +379,24 @@ class EventRuleTest(APITestCase):
# Patch the Session object with our dummy_send() method, then process the webhook for sending # Patch the Session object with our dummy_send() method, then process the webhook for sending
with patch.object(Session, 'send', dummy_send) as mock_send: with patch.object(Session, 'send', dummy_send) as mock_send:
send_webhook(**job.kwargs) send_webhook(**job.kwargs)
def test_duplicate_triggers(self):
"""
Test for erroneous duplicate event triggers resulting from saving an object multiple times
within the span of a single request.
"""
url = reverse('dcim:site_add')
request = RequestFactory().get(url)
request.id = uuid.uuid4()
request.user = self.user
self.assertEqual(self.queue.count, 0, msg="Unexpected jobs found in queue")
with event_tracking(request):
site = Site(name='Site 1', slug='site-1')
site.save()
# Save the site a second time
site.save()
self.assertEqual(self.queue.count, 1, msg="Duplicate jobs found in queue")

View File

@ -649,7 +649,7 @@ class IPAddressTest(APIViewTestCases.APIViewTestCase):
'description': 'New description', 'description': 'New description',
} }
graphql_filter = { graphql_filter = {
'address': '192.168.0.1/24', 'address': {'lookup': 'i_exact', 'value': '192.168.0.1/24'},
} }
@classmethod @classmethod

View File

@ -7,4 +7,4 @@ __all__ = (
current_request = ContextVar('current_request', default=None) current_request = ContextVar('current_request', default=None)
events_queue = ContextVar('events_queue', default=[]) events_queue = ContextVar('events_queue', default=dict())

View File

@ -23,8 +23,9 @@ def map_strawberry_type(field):
elif isinstance(field, MultiValueArrayFilter): elif isinstance(field, MultiValueArrayFilter):
pass pass
elif isinstance(field, MultiValueCharFilter): elif isinstance(field, MultiValueCharFilter):
should_create_function = True # Note: Need to use the legacy FilterLookup from filters, not from
attr_type = List[str] | None # strawberry_django.FilterLookup as we currently have USE_DEPRECATED_FILTERS
attr_type = strawberry_django.filters.FilterLookup[str] | None
elif isinstance(field, MultiValueDateFilter): elif isinstance(field, MultiValueDateFilter):
attr_type = auto attr_type = auto
elif isinstance(field, MultiValueDateTimeFilter): elif isinstance(field, MultiValueDateTimeFilter):

Binary file not shown.

View File

@ -1,3 +1,10 @@
// Disable font-ligatures for Chromium based browsers
// Chromium requires `font-variant-ligatures: none` in addition to `font-feature-settings "liga" 0`
* {
font-feature-settings: "liga" 0;
font-variant-ligatures: none;
}
// Restore default foreground & background colors for <pre> blocks // Restore default foreground & background colors for <pre> blocks
pre { pre {
background-color: transparent; background-color: transparent;

View File

@ -1,5 +1,6 @@
{% extends 'generic/object.html' %} {% extends 'generic/object.html' %}
{% load helpers %} {% load helpers %}
{% load plugins %}
{% load i18n %} {% load i18n %}
{% block title %}{{ object }}{% endblock %} {% block title %}{{ object }}{% endblock %}
@ -22,7 +23,7 @@
{% block subtitle %}{% endblock %} {% block subtitle %}{% endblock %}
{% block content %} {% block content %}
<div class="row mb-3"> <div class="row">
<div class="col col-md-5"> <div class="col col-md-5">
<div class="card"> <div class="card">
<h5 class="card-header">{% trans "Change" %}</h5> <h5 class="card-header">{% trans "Change" %}</h5>
@ -104,7 +105,7 @@
</div> </div>
</div> </div>
</div> </div>
<div class="row mb-3"> <div class="row">
<div class="col col-md-6"> <div class="col col-md-6">
<div class="card"> <div class="card">
<h5 class="card-header">{% trans "Pre-Change Data" %}</h5> <h5 class="card-header">{% trans "Pre-Change Data" %}</h5>
@ -144,7 +145,15 @@
</div> </div>
</div> </div>
</div> </div>
<div class="row mb-3"> <div class="row">
<div class="col col-md-6">
{% plugin_left_page object %}
</div>
<div class="col col-md-6">
{% plugin_right_page object %}
</div>
</div>
<div class="row">
<div class="col col-md-12"> <div class="col col-md-12">
{% include 'inc/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 %} {% if related_changes_count > related_changes_table.rows|length %}
@ -158,4 +167,9 @@
{% endif %} {% endif %}
</div> </div>
</div> </div>
<div class="row">
<div class="col col-md-12">
{% plugin_full_width_page object %}
</div>
</div>
{% endblock %} {% endblock %}

View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-05-30 14:23+0000\n" "POT-Creation-Date: 2024-06-04 05:02+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@ -172,7 +172,7 @@ msgstr ""
#: netbox/dcim/forms/filtersets.py:1524 netbox/dcim/forms/model_forms.py:136 #: netbox/dcim/forms/filtersets.py:1524 netbox/dcim/forms/model_forms.py:136
#: netbox/dcim/forms/model_forms.py:164 netbox/dcim/forms/model_forms.py:206 #: netbox/dcim/forms/model_forms.py:164 netbox/dcim/forms/model_forms.py:206
#: netbox/dcim/forms/model_forms.py:406 netbox/dcim/forms/model_forms.py:668 #: netbox/dcim/forms/model_forms.py:406 netbox/dcim/forms/model_forms.py:668
#: netbox/dcim/forms/object_create.py:391 netbox/dcim/tables/devices.py:158 #: netbox/dcim/forms/object_create.py:391 netbox/dcim/tables/devices.py:150
#: netbox/dcim/tables/power.py:26 netbox/dcim/tables/power.py:93 #: netbox/dcim/tables/power.py:26 netbox/dcim/tables/power.py:93
#: netbox/dcim/tables/racks.py:62 netbox/dcim/tables/racks.py:138 #: netbox/dcim/tables/racks.py:62 netbox/dcim/tables/racks.py:138
#: netbox/dcim/tables/sites.py:129 netbox/extras/filtersets.py:477 #: netbox/dcim/tables/sites.py:129 netbox/extras/filtersets.py:477
@ -492,8 +492,8 @@ msgstr ""
#: netbox/dcim/forms/bulk_edit.py:1071 netbox/dcim/forms/bulk_edit.py:1098 #: netbox/dcim/forms/bulk_edit.py:1071 netbox/dcim/forms/bulk_edit.py:1098
#: netbox/dcim/forms/bulk_edit.py:1571 netbox/dcim/forms/filtersets.py:983 #: netbox/dcim/forms/bulk_edit.py:1571 netbox/dcim/forms/filtersets.py:983
#: netbox/dcim/forms/filtersets.py:1359 netbox/dcim/forms/filtersets.py:1380 #: netbox/dcim/forms/filtersets.py:1359 netbox/dcim/forms/filtersets.py:1380
#: netbox/dcim/tables/devices.py:699 netbox/dcim/tables/devices.py:759 #: netbox/dcim/tables/devices.py:687 netbox/dcim/tables/devices.py:744
#: netbox/dcim/tables/devices.py:986 netbox/dcim/tables/devicetypes.py:245 #: netbox/dcim/tables/devices.py:968 netbox/dcim/tables/devicetypes.py:245
#: netbox/dcim/tables/devicetypes.py:260 netbox/dcim/tables/racks.py:32 #: netbox/dcim/tables/devicetypes.py:260 netbox/dcim/tables/racks.py:32
#: netbox/extras/forms/bulk_edit.py:260 netbox/extras/tables/tables.py:333 #: netbox/extras/forms/bulk_edit.py:260 netbox/extras/tables/tables.py:333
#: netbox/templates/circuits/circuittype.html:30 #: netbox/templates/circuits/circuittype.html:30
@ -527,8 +527,8 @@ msgstr ""
#: netbox/dcim/forms/filtersets.py:1354 netbox/dcim/forms/filtersets.py:1375 #: netbox/dcim/forms/filtersets.py:1354 netbox/dcim/forms/filtersets.py:1375
#: netbox/dcim/forms/model_forms.py:643 netbox/dcim/forms/model_forms.py:649 #: netbox/dcim/forms/model_forms.py:643 netbox/dcim/forms/model_forms.py:649
#: netbox/dcim/forms/object_import.py:84 netbox/dcim/forms/object_import.py:113 #: netbox/dcim/forms/object_import.py:84 netbox/dcim/forms/object_import.py:113
#: netbox/dcim/forms/object_import.py:145 netbox/dcim/tables/devices.py:183 #: netbox/dcim/forms/object_import.py:145 netbox/dcim/tables/devices.py:175
#: netbox/dcim/tables/devices.py:815 netbox/dcim/tables/power.py:77 #: netbox/dcim/tables/devices.py:797 netbox/dcim/tables/power.py:77
#: netbox/extras/forms/bulk_import.py:39 netbox/extras/tables/tables.py:283 #: netbox/extras/forms/bulk_import.py:39 netbox/extras/tables/tables.py:283
#: netbox/extras/tables/tables.py:355 netbox/extras/tables/tables.py:473 #: netbox/extras/tables/tables.py:355 netbox/extras/tables/tables.py:473
#: netbox/netbox/tables/tables.py:239 netbox/templates/circuits/circuit.html:30 #: netbox/netbox/tables/tables.py:239 netbox/templates/circuits/circuit.html:30
@ -583,8 +583,8 @@ msgstr ""
#: netbox/dcim/forms/filtersets.py:282 netbox/dcim/forms/filtersets.py:728 #: netbox/dcim/forms/filtersets.py:282 netbox/dcim/forms/filtersets.py:728
#: netbox/dcim/forms/filtersets.py:843 netbox/dcim/forms/filtersets.py:877 #: netbox/dcim/forms/filtersets.py:843 netbox/dcim/forms/filtersets.py:877
#: netbox/dcim/forms/filtersets.py:978 netbox/dcim/forms/filtersets.py:1089 #: netbox/dcim/forms/filtersets.py:978 netbox/dcim/forms/filtersets.py:1089
#: netbox/dcim/tables/devices.py:145 netbox/dcim/tables/devices.py:818 #: netbox/dcim/tables/devices.py:137 netbox/dcim/tables/devices.py:800
#: netbox/dcim/tables/devices.py:1046 netbox/dcim/tables/modules.py:69 #: netbox/dcim/tables/devices.py:1028 netbox/dcim/tables/modules.py:69
#: netbox/dcim/tables/power.py:74 netbox/dcim/tables/racks.py:66 #: netbox/dcim/tables/power.py:74 netbox/dcim/tables/racks.py:66
#: netbox/dcim/tables/sites.py:82 netbox/dcim/tables/sites.py:133 #: netbox/dcim/tables/sites.py:82 netbox/dcim/tables/sites.py:133
#: netbox/ipam/forms/bulk_edit.py:241 netbox/ipam/forms/bulk_edit.py:290 #: netbox/ipam/forms/bulk_edit.py:241 netbox/ipam/forms/bulk_edit.py:290
@ -868,7 +868,7 @@ msgstr ""
#: netbox/dcim/forms/filtersets.py:1406 netbox/dcim/forms/filtersets.py:1420 #: netbox/dcim/forms/filtersets.py:1406 netbox/dcim/forms/filtersets.py:1420
#: netbox/dcim/forms/model_forms.py:179 netbox/dcim/forms/model_forms.py:211 #: netbox/dcim/forms/model_forms.py:179 netbox/dcim/forms/model_forms.py:211
#: netbox/dcim/forms/model_forms.py:411 netbox/dcim/forms/model_forms.py:673 #: netbox/dcim/forms/model_forms.py:411 netbox/dcim/forms/model_forms.py:673
#: netbox/dcim/tables/devices.py:162 netbox/dcim/tables/power.py:30 #: netbox/dcim/tables/devices.py:154 netbox/dcim/tables/power.py:30
#: netbox/dcim/tables/racks.py:58 netbox/dcim/tables/racks.py:143 #: netbox/dcim/tables/racks.py:58 netbox/dcim/tables/racks.py:143
#: netbox/extras/filtersets.py:488 netbox/extras/forms/filtersets.py:329 #: netbox/extras/filtersets.py:488 netbox/extras/forms/filtersets.py:329
#: netbox/ipam/forms/bulk_edit.py:457 netbox/ipam/forms/filtersets.py:173 #: netbox/ipam/forms/bulk_edit.py:457 netbox/ipam/forms/filtersets.py:173
@ -913,7 +913,7 @@ msgstr ""
#: netbox/dcim/forms/filtersets.py:1055 netbox/dcim/forms/filtersets.py:1468 #: netbox/dcim/forms/filtersets.py:1055 netbox/dcim/forms/filtersets.py:1468
#: netbox/dcim/forms/filtersets.py:1492 netbox/dcim/forms/filtersets.py:1516 #: netbox/dcim/forms/filtersets.py:1492 netbox/dcim/forms/filtersets.py:1516
#: netbox/dcim/forms/model_forms.py:111 netbox/dcim/forms/object_create.py:375 #: netbox/dcim/forms/model_forms.py:111 netbox/dcim/forms/object_create.py:375
#: netbox/dcim/tables/devices.py:148 netbox/dcim/tables/sites.py:85 #: netbox/dcim/tables/devices.py:140 netbox/dcim/tables/sites.py:85
#: netbox/extras/filtersets.py:455 netbox/ipam/forms/bulk_edit.py:206 #: netbox/extras/filtersets.py:455 netbox/ipam/forms/bulk_edit.py:206
#: netbox/ipam/forms/bulk_edit.py:438 netbox/ipam/forms/bulk_edit.py:512 #: netbox/ipam/forms/bulk_edit.py:438 netbox/ipam/forms/bulk_edit.py:512
#: netbox/ipam/forms/filtersets.py:217 netbox/ipam/forms/filtersets.py:422 #: netbox/ipam/forms/filtersets.py:217 netbox/ipam/forms/filtersets.py:422
@ -1097,7 +1097,7 @@ msgstr ""
#: netbox/extras/models/configs.py:45 netbox/extras/models/configs.py:219 #: netbox/extras/models/configs.py:45 netbox/extras/models/configs.py:219
#: netbox/extras/models/customfields.py:123 netbox/extras/models/models.py:60 #: netbox/extras/models/customfields.py:123 netbox/extras/models/models.py:60
#: netbox/extras/models/models.py:186 netbox/extras/models/models.py:424 #: netbox/extras/models/models.py:186 netbox/extras/models/models.py:424
#: netbox/extras/models/models.py:539 netbox/extras/models/staging.py:31 #: netbox/extras/models/models.py:539 netbox/extras/models/staging.py:32
#: netbox/extras/models/tags.py:32 netbox/netbox/models/__init__.py:109 #: netbox/extras/models/tags.py:32 netbox/netbox/models/__init__.py:109
#: netbox/netbox/models/__init__.py:144 netbox/netbox/models/__init__.py:190 #: netbox/netbox/models/__init__.py:144 netbox/netbox/models/__init__.py:190
#: netbox/users/models/permissions.py:24 netbox/users/models/tokens.py:58 #: netbox/users/models/permissions.py:24 netbox/users/models/tokens.py:58
@ -1138,7 +1138,7 @@ msgstr ""
#: netbox/extras/models/models.py:181 netbox/extras/models/models.py:324 #: netbox/extras/models/models.py:181 netbox/extras/models/models.py:324
#: netbox/extras/models/models.py:420 netbox/extras/models/models.py:529 #: netbox/extras/models/models.py:420 netbox/extras/models/models.py:529
#: netbox/extras/models/models.py:624 netbox/extras/models/scripts.py:30 #: netbox/extras/models/models.py:624 netbox/extras/models/scripts.py:30
#: netbox/extras/models/staging.py:26 netbox/ipam/models/asns.py:18 #: netbox/extras/models/staging.py:27 netbox/ipam/models/asns.py:18
#: netbox/ipam/models/fhrp.py:25 netbox/ipam/models/services.py:52 #: netbox/ipam/models/fhrp.py:25 netbox/ipam/models/services.py:52
#: netbox/ipam/models/services.py:88 netbox/ipam/models/vlans.py:26 #: netbox/ipam/models/services.py:88 netbox/ipam/models/vlans.py:26
#: netbox/ipam/models/vlans.py:164 netbox/ipam/models/vrfs.py:22 #: netbox/ipam/models/vlans.py:164 netbox/ipam/models/vrfs.py:22
@ -1207,14 +1207,14 @@ msgstr ""
#: netbox/core/tables/jobs.py:14 netbox/core/tables/plugins.py:13 #: netbox/core/tables/jobs.py:14 netbox/core/tables/plugins.py:13
#: netbox/core/tables/tasks.py:11 netbox/core/tables/tasks.py:115 #: netbox/core/tables/tasks.py:11 netbox/core/tables/tasks.py:115
#: netbox/dcim/forms/filtersets.py:61 netbox/dcim/forms/object_create.py:43 #: netbox/dcim/forms/filtersets.py:61 netbox/dcim/forms/object_create.py:43
#: netbox/dcim/tables/devices.py:60 netbox/dcim/tables/devices.py:97 #: netbox/dcim/tables/devices.py:52 netbox/dcim/tables/devices.py:89
#: netbox/dcim/tables/devices.py:139 netbox/dcim/tables/devices.py:294 #: netbox/dcim/tables/devices.py:131 netbox/dcim/tables/devices.py:286
#: netbox/dcim/tables/devices.py:380 netbox/dcim/tables/devices.py:424 #: netbox/dcim/tables/devices.py:380 netbox/dcim/tables/devices.py:421
#: netbox/dcim/tables/devices.py:476 netbox/dcim/tables/devices.py:528 #: netbox/dcim/tables/devices.py:470 netbox/dcim/tables/devices.py:519
#: netbox/dcim/tables/devices.py:644 netbox/dcim/tables/devices.py:726 #: netbox/dcim/tables/devices.py:632 netbox/dcim/tables/devices.py:714
#: netbox/dcim/tables/devices.py:776 netbox/dcim/tables/devices.py:842 #: netbox/dcim/tables/devices.py:761 netbox/dcim/tables/devices.py:824
#: netbox/dcim/tables/devices.py:957 netbox/dcim/tables/devices.py:977 #: netbox/dcim/tables/devices.py:939 netbox/dcim/tables/devices.py:959
#: netbox/dcim/tables/devices.py:1006 netbox/dcim/tables/devices.py:1036 #: netbox/dcim/tables/devices.py:988 netbox/dcim/tables/devices.py:1018
#: netbox/dcim/tables/devicetypes.py:32 netbox/dcim/tables/power.py:22 #: netbox/dcim/tables/devicetypes.py:32 netbox/dcim/tables/power.py:22
#: netbox/dcim/tables/power.py:62 netbox/dcim/tables/racks.py:23 #: netbox/dcim/tables/power.py:62 netbox/dcim/tables/racks.py:23
#: netbox/dcim/tables/racks.py:53 netbox/dcim/tables/sites.py:24 #: netbox/dcim/tables/racks.py:53 netbox/dcim/tables/sites.py:24
@ -1304,7 +1304,7 @@ msgstr ""
#: netbox/virtualization/tables/clusters.py:62 #: netbox/virtualization/tables/clusters.py:62
#: netbox/virtualization/tables/virtualmachines.py:54 #: netbox/virtualization/tables/virtualmachines.py:54
#: netbox/virtualization/tables/virtualmachines.py:132 #: netbox/virtualization/tables/virtualmachines.py:132
#: netbox/virtualization/tables/virtualmachines.py:185 #: netbox/virtualization/tables/virtualmachines.py:187
#: netbox/vpn/tables/crypto.py:18 netbox/vpn/tables/crypto.py:57 #: netbox/vpn/tables/crypto.py:18 netbox/vpn/tables/crypto.py:57
#: netbox/vpn/tables/crypto.py:93 netbox/vpn/tables/crypto.py:129 #: netbox/vpn/tables/crypto.py:93 netbox/vpn/tables/crypto.py:129
#: netbox/vpn/tables/crypto.py:158 netbox/vpn/tables/l2vpn.py:23 #: netbox/vpn/tables/crypto.py:158 netbox/vpn/tables/l2vpn.py:23
@ -1344,7 +1344,7 @@ msgstr ""
#: netbox/circuits/tables/circuits.py:76 netbox/circuits/tables/providers.py:48 #: netbox/circuits/tables/circuits.py:76 netbox/circuits/tables/providers.py:48
#: netbox/circuits/tables/providers.py:82 #: netbox/circuits/tables/providers.py:82
#: netbox/circuits/tables/providers.py:107 netbox/dcim/tables/devices.py:1019 #: netbox/circuits/tables/providers.py:107 netbox/dcim/tables/devices.py:1001
#: netbox/dcim/tables/devicetypes.py:92 netbox/dcim/tables/modules.py:29 #: netbox/dcim/tables/devicetypes.py:92 netbox/dcim/tables/modules.py:29
#: netbox/dcim/tables/modules.py:72 netbox/dcim/tables/power.py:39 #: netbox/dcim/tables/modules.py:72 netbox/dcim/tables/power.py:39
#: netbox/dcim/tables/power.py:96 netbox/dcim/tables/racks.py:76 #: netbox/dcim/tables/power.py:96 netbox/dcim/tables/racks.py:76
@ -1515,7 +1515,7 @@ msgstr ""
#: netbox/core/forms/bulk_edit.py:25 netbox/core/forms/filtersets.py:40 #: netbox/core/forms/bulk_edit.py:25 netbox/core/forms/filtersets.py:40
#: netbox/core/tables/data.py:26 netbox/dcim/forms/bulk_edit.py:1020 #: netbox/core/tables/data.py:26 netbox/dcim/forms/bulk_edit.py:1020
#: netbox/dcim/forms/bulk_edit.py:1293 netbox/dcim/forms/filtersets.py:1276 #: netbox/dcim/forms/bulk_edit.py:1293 netbox/dcim/forms/filtersets.py:1276
#: netbox/dcim/tables/devices.py:553 netbox/dcim/tables/devicetypes.py:221 #: netbox/dcim/tables/devices.py:541 netbox/dcim/tables/devicetypes.py:221
#: netbox/extras/forms/bulk_edit.py:98 netbox/extras/forms/bulk_edit.py:162 #: netbox/extras/forms/bulk_edit.py:98 netbox/extras/forms/bulk_edit.py:162
#: netbox/extras/forms/bulk_edit.py:221 netbox/extras/forms/filtersets.py:120 #: netbox/extras/forms/bulk_edit.py:221 netbox/extras/forms/filtersets.py:120
#: netbox/extras/forms/filtersets.py:207 netbox/extras/forms/filtersets.py:268 #: netbox/extras/forms/filtersets.py:207 netbox/extras/forms/filtersets.py:268
@ -1918,7 +1918,7 @@ msgid "completed"
msgstr "" msgstr ""
#: netbox/core/models/jobs.py:91 netbox/extras/models/models.py:121 #: netbox/core/models/jobs.py:91 netbox/extras/models/models.py:121
#: netbox/extras/models/staging.py:87 #: netbox/extras/models/staging.py:88
msgid "data" msgid "data"
msgstr "" msgstr ""
@ -2163,7 +2163,7 @@ msgstr ""
#: netbox/dcim/forms/model_forms.py:73 netbox/dcim/forms/model_forms.py:92 #: netbox/dcim/forms/model_forms.py:73 netbox/dcim/forms/model_forms.py:92
#: netbox/dcim/forms/model_forms.py:169 netbox/dcim/forms/model_forms.py:1007 #: netbox/dcim/forms/model_forms.py:169 netbox/dcim/forms/model_forms.py:1007
#: netbox/dcim/forms/model_forms.py:1446 netbox/dcim/forms/object_import.py:176 #: netbox/dcim/forms/model_forms.py:1446 netbox/dcim/forms/object_import.py:176
#: netbox/dcim/tables/devices.py:652 netbox/dcim/tables/devices.py:937 #: netbox/dcim/tables/devices.py:640 netbox/dcim/tables/devices.py:919
#: netbox/extras/tables/tables.py:186 netbox/ipam/tables/fhrp.py:59 #: netbox/extras/tables/tables.py:186 netbox/ipam/tables/fhrp.py:59
#: netbox/ipam/tables/ip.py:374 netbox/ipam/tables/services.py:44 #: netbox/ipam/tables/ip.py:374 netbox/ipam/tables/services.py:44
#: netbox/templates/dcim/interface.html:102 #: netbox/templates/dcim/interface.html:102
@ -2297,7 +2297,7 @@ msgstr ""
#: netbox/dcim/choices.py:979 netbox/dcim/forms/bulk_edit.py:1303 #: netbox/dcim/choices.py:979 netbox/dcim/forms/bulk_edit.py:1303
#: netbox/dcim/forms/bulk_import.py:785 netbox/dcim/forms/model_forms.py:919 #: netbox/dcim/forms/bulk_import.py:785 netbox/dcim/forms/model_forms.py:919
#: netbox/dcim/tables/devices.py:656 netbox/templates/dcim/interface.html:106 #: netbox/dcim/tables/devices.py:644 netbox/templates/dcim/interface.html:106
#: netbox/templates/virtualization/vminterface.html:43 #: netbox/templates/virtualization/vminterface.html:43
#: netbox/virtualization/forms/bulk_edit.py:212 #: netbox/virtualization/forms/bulk_edit.py:212
#: netbox/virtualization/forms/bulk_import.py:158 #: netbox/virtualization/forms/bulk_import.py:158
@ -2781,7 +2781,7 @@ msgid "Virtual Chassis (ID)"
msgstr "" msgstr ""
#: netbox/dcim/filtersets.py:1401 netbox/dcim/forms/filtersets.py:107 #: netbox/dcim/filtersets.py:1401 netbox/dcim/forms/filtersets.py:107
#: netbox/dcim/tables/devices.py:211 netbox/netbox/navigation/menu.py:66 #: netbox/dcim/tables/devices.py:203 netbox/netbox/navigation/menu.py:66
#: netbox/templates/dcim/device.html:120 #: netbox/templates/dcim/device.html:120
#: netbox/templates/dcim/device_edit.html:93 #: netbox/templates/dcim/device_edit.html:93
#: netbox/templates/dcim/virtualchassis.html:20 #: netbox/templates/dcim/virtualchassis.html:20
@ -2811,7 +2811,7 @@ msgstr ""
#: netbox/dcim/forms/bulk_import.py:836 netbox/dcim/forms/filtersets.py:1334 #: netbox/dcim/forms/bulk_import.py:836 netbox/dcim/forms/filtersets.py:1334
#: netbox/dcim/forms/model_forms.py:1322 #: netbox/dcim/forms/model_forms.py:1322
#: netbox/dcim/models/device_components.py:712 #: netbox/dcim/models/device_components.py:712
#: netbox/dcim/tables/devices.py:622 netbox/ipam/filtersets.py:316 #: netbox/dcim/tables/devices.py:610 netbox/ipam/filtersets.py:316
#: netbox/ipam/filtersets.py:327 netbox/ipam/filtersets.py:483 #: netbox/ipam/filtersets.py:327 netbox/ipam/filtersets.py:483
#: netbox/ipam/filtersets.py:584 netbox/ipam/filtersets.py:595 #: netbox/ipam/filtersets.py:584 netbox/ipam/filtersets.py:595
#: netbox/ipam/forms/bulk_edit.py:227 netbox/ipam/forms/bulk_edit.py:282 #: netbox/ipam/forms/bulk_edit.py:227 netbox/ipam/forms/bulk_edit.py:282
@ -2852,7 +2852,7 @@ msgid "L2VPN (ID)"
msgstr "" msgstr ""
#: netbox/dcim/filtersets.py:1563 netbox/dcim/forms/filtersets.py:1339 #: netbox/dcim/filtersets.py:1563 netbox/dcim/forms/filtersets.py:1339
#: netbox/dcim/tables/devices.py:570 netbox/ipam/filtersets.py:1022 #: netbox/dcim/tables/devices.py:558 netbox/ipam/filtersets.py:1022
#: netbox/ipam/forms/filtersets.py:525 netbox/ipam/tables/vlans.py:133 #: netbox/ipam/forms/filtersets.py:525 netbox/ipam/tables/vlans.py:133
#: netbox/templates/dcim/interface.html:93 netbox/templates/ipam/vlan.html:66 #: netbox/templates/dcim/interface.html:93 netbox/templates/ipam/vlan.html:66
#: netbox/templates/vpn/l2vpntermination.html:12 #: netbox/templates/vpn/l2vpntermination.html:12
@ -2902,7 +2902,7 @@ msgstr ""
msgid "Wireless LAN" msgid "Wireless LAN"
msgstr "" msgstr ""
#: netbox/dcim/filtersets.py:1667 netbox/dcim/tables/devices.py:609 #: netbox/dcim/filtersets.py:1667 netbox/dcim/tables/devices.py:597
msgid "Wireless link" msgid "Wireless link"
msgstr "" msgstr ""
@ -2957,8 +2957,8 @@ msgstr ""
#: netbox/dcim/forms/bulk_create.py:112 netbox/dcim/forms/filtersets.py:1396 #: netbox/dcim/forms/bulk_create.py:112 netbox/dcim/forms/filtersets.py:1396
#: netbox/dcim/forms/model_forms.py:431 netbox/dcim/forms/model_forms.py:486 #: netbox/dcim/forms/model_forms.py:431 netbox/dcim/forms/model_forms.py:486
#: netbox/dcim/forms/object_create.py:197 #: netbox/dcim/forms/object_create.py:197
#: netbox/dcim/forms/object_create.py:353 netbox/dcim/tables/devices.py:170 #: netbox/dcim/forms/object_create.py:353 netbox/dcim/tables/devices.py:162
#: netbox/dcim/tables/devices.py:702 netbox/dcim/tables/devicetypes.py:242 #: netbox/dcim/tables/devices.py:690 netbox/dcim/tables/devicetypes.py:242
#: netbox/templates/dcim/device.html:43 netbox/templates/dcim/device.html:130 #: netbox/templates/dcim/device.html:43 netbox/templates/dcim/device.html:130
#: netbox/templates/dcim/modulebay.html:34 #: netbox/templates/dcim/modulebay.html:34
#: netbox/templates/dcim/virtualchassis.html:66 #: netbox/templates/dcim/virtualchassis.html:66
@ -3035,8 +3035,8 @@ msgstr ""
#: netbox/dcim/forms/filtersets.py:706 netbox/dcim/forms/filtersets.py:1426 #: netbox/dcim/forms/filtersets.py:706 netbox/dcim/forms/filtersets.py:1426
#: netbox/dcim/forms/model_forms.py:219 netbox/dcim/forms/model_forms.py:1015 #: netbox/dcim/forms/model_forms.py:219 netbox/dcim/forms/model_forms.py:1015
#: netbox/dcim/forms/model_forms.py:1454 netbox/dcim/forms/object_import.py:181 #: netbox/dcim/forms/model_forms.py:1454 netbox/dcim/forms/object_import.py:181
#: netbox/dcim/tables/devices.py:174 netbox/dcim/tables/devices.py:810 #: netbox/dcim/tables/devices.py:166 netbox/dcim/tables/devices.py:792
#: netbox/dcim/tables/devices.py:921 netbox/dcim/tables/devicetypes.py:300 #: netbox/dcim/tables/devices.py:903 netbox/dcim/tables/devicetypes.py:300
#: netbox/dcim/tables/racks.py:69 netbox/extras/filtersets.py:504 #: netbox/dcim/tables/racks.py:69 netbox/extras/filtersets.py:504
#: netbox/ipam/forms/bulk_edit.py:246 netbox/ipam/forms/bulk_edit.py:295 #: netbox/ipam/forms/bulk_edit.py:246 netbox/ipam/forms/bulk_edit.py:295
#: netbox/ipam/forms/bulk_edit.py:343 netbox/ipam/forms/bulk_edit.py:549 #: netbox/ipam/forms/bulk_edit.py:343 netbox/ipam/forms/bulk_edit.py:549
@ -3159,7 +3159,7 @@ msgstr ""
#: netbox/dcim/forms/filtersets.py:954 netbox/dcim/forms/filtersets.py:1086 #: netbox/dcim/forms/filtersets.py:954 netbox/dcim/forms/filtersets.py:1086
#: netbox/dcim/forms/model_forms.py:226 netbox/dcim/forms/model_forms.py:248 #: netbox/dcim/forms/model_forms.py:226 netbox/dcim/forms/model_forms.py:248
#: netbox/dcim/forms/model_forms.py:422 netbox/dcim/forms/model_forms.py:700 #: netbox/dcim/forms/model_forms.py:422 netbox/dcim/forms/model_forms.py:700
#: netbox/dcim/forms/object_create.py:400 netbox/dcim/tables/devices.py:166 #: netbox/dcim/forms/object_create.py:400 netbox/dcim/tables/devices.py:158
#: netbox/dcim/tables/power.py:70 netbox/dcim/tables/racks.py:148 #: netbox/dcim/tables/power.py:70 netbox/dcim/tables/racks.py:148
#: netbox/ipam/forms/bulk_edit.py:465 netbox/ipam/forms/filtersets.py:442 #: netbox/ipam/forms/bulk_edit.py:465 netbox/ipam/forms/filtersets.py:442
#: netbox/ipam/forms/model_forms.py:610 netbox/templates/dcim/device.html:30 #: netbox/ipam/forms/model_forms.py:610 netbox/templates/dcim/device.html:30
@ -3193,8 +3193,8 @@ msgstr ""
#: netbox/dcim/forms/model_forms.py:281 netbox/dcim/forms/model_forms.py:293 #: netbox/dcim/forms/model_forms.py:281 netbox/dcim/forms/model_forms.py:293
#: netbox/dcim/forms/model_forms.py:339 netbox/dcim/forms/model_forms.py:379 #: netbox/dcim/forms/model_forms.py:339 netbox/dcim/forms/model_forms.py:379
#: netbox/dcim/forms/model_forms.py:1020 netbox/dcim/forms/model_forms.py:1459 #: netbox/dcim/forms/model_forms.py:1020 netbox/dcim/forms/model_forms.py:1459
#: netbox/dcim/forms/object_import.py:187 netbox/dcim/tables/devices.py:101 #: netbox/dcim/forms/object_import.py:187 netbox/dcim/tables/devices.py:93
#: netbox/dcim/tables/devices.py:177 netbox/dcim/tables/devices.py:924 #: netbox/dcim/tables/devices.py:169 netbox/dcim/tables/devices.py:906
#: netbox/dcim/tables/devicetypes.py:81 netbox/dcim/tables/devicetypes.py:304 #: netbox/dcim/tables/devicetypes.py:81 netbox/dcim/tables/devicetypes.py:304
#: netbox/dcim/tables/modules.py:20 netbox/dcim/tables/modules.py:60 #: netbox/dcim/tables/modules.py:20 netbox/dcim/tables/modules.py:60
#: netbox/templates/dcim/devicetype.html:14 #: netbox/templates/dcim/devicetype.html:14
@ -3277,7 +3277,7 @@ msgstr ""
#: netbox/dcim/forms/bulk_edit.py:593 netbox/dcim/forms/bulk_import.py:443 #: netbox/dcim/forms/bulk_edit.py:593 netbox/dcim/forms/bulk_import.py:443
#: netbox/dcim/forms/filtersets.py:725 netbox/dcim/forms/model_forms.py:394 #: netbox/dcim/forms/filtersets.py:725 netbox/dcim/forms/model_forms.py:394
#: netbox/dcim/forms/model_forms.py:456 netbox/dcim/tables/devices.py:187 #: netbox/dcim/forms/model_forms.py:456 netbox/dcim/tables/devices.py:179
#: netbox/extras/filtersets.py:515 netbox/templates/dcim/device.html:184 #: netbox/extras/filtersets.py:515 netbox/templates/dcim/device.html:184
#: netbox/templates/dcim/platform.html:26 #: netbox/templates/dcim/platform.html:26
#: netbox/templates/virtualization/virtualmachine.html:27 #: netbox/templates/virtualization/virtualmachine.html:27
@ -3309,13 +3309,13 @@ msgstr ""
#: netbox/dcim/forms/model_forms.py:794 netbox/dcim/forms/model_forms.py:1153 #: netbox/dcim/forms/model_forms.py:794 netbox/dcim/forms/model_forms.py:1153
#: netbox/dcim/forms/model_forms.py:1608 netbox/dcim/forms/object_create.py:257 #: netbox/dcim/forms/model_forms.py:1608 netbox/dcim/forms/object_create.py:257
#: netbox/dcim/tables/connections.py:22 netbox/dcim/tables/connections.py:41 #: netbox/dcim/tables/connections.py:22 netbox/dcim/tables/connections.py:41
#: netbox/dcim/tables/connections.py:60 netbox/dcim/tables/devices.py:290 #: netbox/dcim/tables/connections.py:60 netbox/dcim/tables/devices.py:282
#: netbox/dcim/tables/devices.py:359 netbox/dcim/tables/devices.py:403 #: netbox/dcim/tables/devices.py:359 netbox/dcim/tables/devices.py:400
#: netbox/dcim/tables/devices.py:448 netbox/dcim/tables/devices.py:502 #: netbox/dcim/tables/devices.py:442 netbox/dcim/tables/devices.py:493
#: netbox/dcim/tables/devices.py:594 netbox/dcim/tables/devices.py:692 #: netbox/dcim/tables/devices.py:582 netbox/dcim/tables/devices.py:680
#: netbox/dcim/tables/devices.py:752 netbox/dcim/tables/devices.py:802 #: netbox/dcim/tables/devices.py:737 netbox/dcim/tables/devices.py:784
#: netbox/dcim/tables/devices.py:862 netbox/dcim/tables/devices.py:914 #: netbox/dcim/tables/devices.py:844 netbox/dcim/tables/devices.py:896
#: netbox/dcim/tables/devices.py:1040 netbox/dcim/tables/modules.py:52 #: netbox/dcim/tables/devices.py:1022 netbox/dcim/tables/modules.py:52
#: netbox/extras/forms/filtersets.py:330 netbox/ipam/forms/bulk_import.py:303 #: netbox/extras/forms/filtersets.py:330 netbox/ipam/forms/bulk_import.py:303
#: netbox/ipam/forms/bulk_import.py:489 netbox/ipam/forms/filtersets.py:558 #: netbox/ipam/forms/bulk_import.py:489 netbox/ipam/forms/filtersets.py:558
#: netbox/ipam/forms/model_forms.py:317 netbox/ipam/forms/model_forms.py:725 #: netbox/ipam/forms/model_forms.py:317 netbox/ipam/forms/model_forms.py:725
@ -3489,7 +3489,7 @@ msgid "Wireless role"
msgstr "" msgstr ""
#: netbox/dcim/forms/bulk_edit.py:1186 netbox/dcim/forms/model_forms.py:609 #: netbox/dcim/forms/bulk_edit.py:1186 netbox/dcim/forms/model_forms.py:609
#: netbox/dcim/forms/model_forms.py:1168 netbox/dcim/tables/devices.py:313 #: netbox/dcim/forms/model_forms.py:1168 netbox/dcim/tables/devices.py:305
#: netbox/templates/dcim/consoleport.html:24 #: netbox/templates/dcim/consoleport.html:24
#: netbox/templates/dcim/consoleserverport.html:24 #: netbox/templates/dcim/consoleserverport.html:24
#: netbox/templates/dcim/frontport.html:24 #: netbox/templates/dcim/frontport.html:24
@ -3501,7 +3501,7 @@ msgstr ""
msgid "Module" msgid "Module"
msgstr "" msgstr ""
#: netbox/dcim/forms/bulk_edit.py:1313 netbox/dcim/tables/devices.py:661 #: netbox/dcim/forms/bulk_edit.py:1313 netbox/dcim/tables/devices.py:649
#: netbox/templates/dcim/interface.html:110 #: netbox/templates/dcim/interface.html:110
msgid "LAG" msgid "LAG"
msgstr "" msgstr ""
@ -3513,7 +3513,7 @@ msgstr ""
#: netbox/dcim/forms/bulk_edit.py:1324 netbox/dcim/forms/bulk_import.py:659 #: netbox/dcim/forms/bulk_edit.py:1324 netbox/dcim/forms/bulk_import.py:659
#: netbox/dcim/forms/bulk_import.py:685 netbox/dcim/forms/filtersets.py:1169 #: netbox/dcim/forms/bulk_import.py:685 netbox/dcim/forms/filtersets.py:1169
#: netbox/dcim/forms/filtersets.py:1191 netbox/dcim/forms/filtersets.py:1264 #: netbox/dcim/forms/filtersets.py:1191 netbox/dcim/forms/filtersets.py:1264
#: netbox/dcim/tables/devices.py:606 #: netbox/dcim/tables/devices.py:594
#: netbox/templates/circuits/inc/circuit_termination_fields.html:67 #: netbox/templates/circuits/inc/circuit_termination_fields.html:67
#: netbox/templates/dcim/consoleport.html:40 #: netbox/templates/dcim/consoleport.html:40
#: netbox/templates/dcim/consoleserverport.html:40 #: netbox/templates/dcim/consoleserverport.html:40
@ -3542,14 +3542,14 @@ msgid "VLAN group"
msgstr "" msgstr ""
#: netbox/dcim/forms/bulk_edit.py:1369 netbox/dcim/forms/model_forms.py:1304 #: netbox/dcim/forms/bulk_edit.py:1369 netbox/dcim/forms/model_forms.py:1304
#: netbox/dcim/tables/devices.py:579 #: netbox/dcim/tables/devices.py:567
#: netbox/virtualization/forms/bulk_edit.py:248 #: netbox/virtualization/forms/bulk_edit.py:248
#: netbox/virtualization/forms/model_forms.py:326 #: netbox/virtualization/forms/model_forms.py:326
msgid "Untagged VLAN" msgid "Untagged VLAN"
msgstr "" msgstr ""
#: netbox/dcim/forms/bulk_edit.py:1377 netbox/dcim/forms/model_forms.py:1313 #: netbox/dcim/forms/bulk_edit.py:1377 netbox/dcim/forms/model_forms.py:1313
#: netbox/dcim/tables/devices.py:585 #: netbox/dcim/tables/devices.py:573
#: netbox/virtualization/forms/bulk_edit.py:256 #: netbox/virtualization/forms/bulk_edit.py:256
#: netbox/virtualization/forms/model_forms.py:335 #: netbox/virtualization/forms/model_forms.py:335
msgid "Tagged VLANs" msgid "Tagged VLANs"
@ -3560,7 +3560,7 @@ msgid "Wireless LAN group"
msgstr "" msgstr ""
#: netbox/dcim/forms/bulk_edit.py:1392 netbox/dcim/forms/model_forms.py:1291 #: netbox/dcim/forms/bulk_edit.py:1392 netbox/dcim/forms/model_forms.py:1291
#: netbox/dcim/tables/devices.py:615 netbox/netbox/navigation/menu.py:133 #: netbox/dcim/tables/devices.py:603 netbox/netbox/navigation/menu.py:133
#: netbox/templates/dcim/interface.html:280 #: netbox/templates/dcim/interface.html:280
#: netbox/wireless/tables/wirelesslan.py:24 #: netbox/wireless/tables/wirelesslan.py:24
msgid "Wireless LANs" msgid "Wireless LANs"
@ -3740,7 +3740,7 @@ msgid "Virtual chassis"
msgstr "" msgstr ""
#: netbox/dcim/forms/bulk_import.py:462 netbox/dcim/forms/model_forms.py:465 #: netbox/dcim/forms/bulk_import.py:462 netbox/dcim/forms/model_forms.py:465
#: netbox/dcim/tables/devices.py:207 netbox/extras/filtersets.py:548 #: netbox/dcim/tables/devices.py:199 netbox/extras/filtersets.py:548
#: netbox/extras/forms/filtersets.py:331 netbox/ipam/forms/bulk_edit.py:479 #: netbox/extras/forms/filtersets.py:331 netbox/ipam/forms/bulk_edit.py:479
#: netbox/ipam/forms/filtersets.py:415 netbox/ipam/forms/filtersets.py:459 #: netbox/ipam/forms/filtersets.py:415 netbox/ipam/forms/filtersets.py:459
#: netbox/ipam/forms/model_forms.py:627 netbox/templates/dcim/device.html:232 #: netbox/ipam/forms/model_forms.py:627 netbox/templates/dcim/device.html:232
@ -3935,7 +3935,7 @@ msgstr ""
msgid "Physical medium classification" msgid "Physical medium classification"
msgstr "" msgstr ""
#: netbox/dcim/forms/bulk_import.py:973 netbox/dcim/tables/devices.py:823 #: netbox/dcim/forms/bulk_import.py:973 netbox/dcim/tables/devices.py:805
msgid "Installed device" msgid "Installed device"
msgstr "" msgstr ""
@ -4024,7 +4024,7 @@ msgid "{side_upper} side termination not found: {device} {name}"
msgstr "" msgstr ""
#: netbox/dcim/forms/bulk_import.py:1244 netbox/dcim/forms/model_forms.py:730 #: netbox/dcim/forms/bulk_import.py:1244 netbox/dcim/forms/model_forms.py:730
#: netbox/dcim/tables/devices.py:1010 netbox/templates/dcim/device.html:131 #: netbox/dcim/tables/devices.py:992 netbox/templates/dcim/device.html:131
#: netbox/templates/dcim/virtualchassis.html:27 #: netbox/templates/dcim/virtualchassis.html:27
#: netbox/templates/dcim/virtualchassis.html:67 #: netbox/templates/dcim/virtualchassis.html:67
msgid "Master" msgid "Master"
@ -4205,7 +4205,7 @@ msgid "Transmit power (dBm)"
msgstr "" msgstr ""
#: netbox/dcim/forms/filtersets.py:1350 netbox/dcim/forms/filtersets.py:1372 #: netbox/dcim/forms/filtersets.py:1350 netbox/dcim/forms/filtersets.py:1372
#: netbox/dcim/tables/devices.py:324 netbox/templates/dcim/cable.html:12 #: netbox/dcim/tables/devices.py:316 netbox/templates/dcim/cable.html:12
#: netbox/templates/dcim/cable_trace.html:46 #: netbox/templates/dcim/cable_trace.html:46
#: netbox/templates/dcim/frontport.html:77 #: netbox/templates/dcim/frontport.html:77
#: netbox/templates/dcim/htmx/cable_edit.html:50 #: netbox/templates/dcim/htmx/cable_edit.html:50
@ -4215,7 +4215,7 @@ msgstr ""
msgid "Cable" msgid "Cable"
msgstr "" msgstr ""
#: netbox/dcim/forms/filtersets.py:1442 netbox/dcim/tables/devices.py:933 #: netbox/dcim/forms/filtersets.py:1442 netbox/dcim/tables/devices.py:915
msgid "Discovered" msgid "Discovered"
msgstr "" msgstr ""
@ -4381,7 +4381,7 @@ msgid "Front Port"
msgstr "" msgstr ""
#: netbox/dcim/forms/model_forms.py:1093 netbox/dcim/forms/model_forms.py:1531 #: netbox/dcim/forms/model_forms.py:1093 netbox/dcim/forms/model_forms.py:1531
#: netbox/dcim/tables/devices.py:705 #: netbox/dcim/tables/devices.py:693
#: netbox/templates/circuits/inc/circuit_termination_fields.html:53 #: netbox/templates/circuits/inc/circuit_termination_fields.html:53
#: netbox/templates/dcim/consoleport.html:79 #: netbox/templates/dcim/consoleport.html:79
#: netbox/templates/dcim/consoleserverport.html:80 #: netbox/templates/dcim/consoleserverport.html:80
@ -4394,7 +4394,7 @@ msgid "Rear Port"
msgstr "" msgstr ""
#: netbox/dcim/forms/model_forms.py:1094 netbox/dcim/forms/model_forms.py:1532 #: netbox/dcim/forms/model_forms.py:1094 netbox/dcim/forms/model_forms.py:1532
#: netbox/dcim/tables/connections.py:46 netbox/dcim/tables/devices.py:509 #: netbox/dcim/tables/connections.py:46 netbox/dcim/tables/devices.py:500
#: netbox/templates/dcim/poweroutlet.html:44 #: netbox/templates/dcim/poweroutlet.html:44
#: netbox/templates/dcim/powerport.html:17 #: netbox/templates/dcim/powerport.html:17
msgid "Power Port" msgid "Power Port"
@ -4481,7 +4481,7 @@ msgid ""
msgstr "" msgstr ""
#: netbox/dcim/forms/object_create.py:110 #: netbox/dcim/forms/object_create.py:110
#: netbox/dcim/forms/object_create.py:271 netbox/dcim/tables/devices.py:257 #: netbox/dcim/forms/object_create.py:271 netbox/dcim/tables/devices.py:249
msgid "Rear ports" msgid "Rear ports"
msgstr "" msgstr ""
@ -4511,7 +4511,7 @@ msgid ""
"selected number of rear port positions ({rearport_count})." "selected number of rear port positions ({rearport_count})."
msgstr "" msgstr ""
#: netbox/dcim/forms/object_create.py:409 netbox/dcim/tables/devices.py:1016 #: netbox/dcim/forms/object_create.py:409 netbox/dcim/tables/devices.py:998
#: netbox/ipam/tables/fhrp.py:31 netbox/templates/dcim/virtualchassis.html:53 #: netbox/ipam/tables/fhrp.py:31 netbox/templates/dcim/virtualchassis.html:53
#: netbox/templates/dcim/virtualchassis_edit.html:47 #: netbox/templates/dcim/virtualchassis_edit.html:47
#: netbox/templates/ipam/fhrpgroup.html:38 #: netbox/templates/ipam/fhrpgroup.html:38
@ -5968,7 +5968,7 @@ msgstr ""
msgid "Reachable" msgid "Reachable"
msgstr "" msgstr ""
#: netbox/dcim/tables/devices.py:66 netbox/dcim/tables/devices.py:111 #: netbox/dcim/tables/devices.py:58 netbox/dcim/tables/devices.py:103
#: netbox/dcim/tables/racks.py:81 netbox/dcim/tables/sites.py:143 #: netbox/dcim/tables/racks.py:81 netbox/dcim/tables/sites.py:143
#: netbox/extras/tables/tables.py:435 netbox/netbox/navigation/menu.py:56 #: netbox/extras/tables/tables.py:435 netbox/netbox/navigation/menu.py:56
#: netbox/netbox/navigation/menu.py:60 netbox/netbox/navigation/menu.py:62 #: netbox/netbox/navigation/menu.py:60 netbox/netbox/navigation/menu.py:62
@ -5978,12 +5978,12 @@ msgstr ""
msgid "Devices" msgid "Devices"
msgstr "" msgstr ""
#: netbox/dcim/tables/devices.py:71 netbox/dcim/tables/devices.py:116 #: netbox/dcim/tables/devices.py:63 netbox/dcim/tables/devices.py:108
#: netbox/virtualization/tables/clusters.py:88 #: netbox/virtualization/tables/clusters.py:88
msgid "VMs" msgid "VMs"
msgstr "" msgstr ""
#: netbox/dcim/tables/devices.py:105 netbox/dcim/tables/devices.py:221 #: netbox/dcim/tables/devices.py:97 netbox/dcim/tables/devices.py:213
#: netbox/extras/forms/model_forms.py:506 netbox/templates/dcim/device.html:112 #: netbox/extras/forms/model_forms.py:506 netbox/templates/dcim/device.html:112
#: netbox/templates/dcim/device/render_config.html:11 #: netbox/templates/dcim/device/render_config.html:11
#: netbox/templates/dcim/device/render_config.html:14 #: netbox/templates/dcim/device/render_config.html:14
@ -5997,11 +5997,11 @@ msgstr ""
msgid "Config Template" msgid "Config Template"
msgstr "" msgstr ""
#: netbox/dcim/tables/devices.py:155 netbox/templates/dcim/sitegroup.html:26 #: netbox/dcim/tables/devices.py:147 netbox/templates/dcim/sitegroup.html:26
msgid "Site Group" msgid "Site Group"
msgstr "" msgstr ""
#: netbox/dcim/tables/devices.py:192 netbox/dcim/tables/devices.py:1051 #: netbox/dcim/tables/devices.py:184 netbox/dcim/tables/devices.py:1033
#: netbox/ipam/forms/bulk_import.py:511 netbox/ipam/forms/model_forms.py:304 #: netbox/ipam/forms/bulk_import.py:511 netbox/ipam/forms/model_forms.py:304
#: netbox/ipam/forms/model_forms.py:313 netbox/ipam/tables/ip.py:352 #: netbox/ipam/forms/model_forms.py:313 netbox/ipam/tables/ip.py:352
#: netbox/ipam/tables/ip.py:418 netbox/ipam/tables/ip.py:441 #: netbox/ipam/tables/ip.py:418 netbox/ipam/tables/ip.py:441
@ -6010,50 +6010,50 @@ msgstr ""
msgid "IP Address" msgid "IP Address"
msgstr "" msgstr ""
#: netbox/dcim/tables/devices.py:196 netbox/dcim/tables/devices.py:1055 #: netbox/dcim/tables/devices.py:188 netbox/dcim/tables/devices.py:1037
#: netbox/virtualization/tables/virtualmachines.py:85 #: netbox/virtualization/tables/virtualmachines.py:85
msgid "IPv4 Address" msgid "IPv4 Address"
msgstr "" msgstr ""
#: netbox/dcim/tables/devices.py:200 netbox/dcim/tables/devices.py:1059 #: netbox/dcim/tables/devices.py:192 netbox/dcim/tables/devices.py:1041
#: netbox/virtualization/tables/virtualmachines.py:89 #: netbox/virtualization/tables/virtualmachines.py:89
msgid "IPv6 Address" msgid "IPv6 Address"
msgstr "" msgstr ""
#: netbox/dcim/tables/devices.py:215 #: netbox/dcim/tables/devices.py:207
msgid "VC Position" msgid "VC Position"
msgstr "" msgstr ""
#: netbox/dcim/tables/devices.py:218 #: netbox/dcim/tables/devices.py:210
msgid "VC Priority" msgid "VC Priority"
msgstr "" msgstr ""
#: netbox/dcim/tables/devices.py:225 netbox/templates/dcim/device_edit.html:38 #: netbox/dcim/tables/devices.py:217 netbox/templates/dcim/device_edit.html:38
#: netbox/templates/dcim/devicebay_populate.html:16 #: netbox/templates/dcim/devicebay_populate.html:16
msgid "Parent Device" msgid "Parent Device"
msgstr "" msgstr ""
#: netbox/dcim/tables/devices.py:230 #: netbox/dcim/tables/devices.py:222
msgid "Position (Device Bay)" msgid "Position (Device Bay)"
msgstr "" msgstr ""
#: netbox/dcim/tables/devices.py:239 #: netbox/dcim/tables/devices.py:231
msgid "Console ports" msgid "Console ports"
msgstr "" msgstr ""
#: netbox/dcim/tables/devices.py:242 #: netbox/dcim/tables/devices.py:234
msgid "Console server ports" msgid "Console server ports"
msgstr "" msgstr ""
#: netbox/dcim/tables/devices.py:245 #: netbox/dcim/tables/devices.py:237
msgid "Power ports" msgid "Power ports"
msgstr "" msgstr ""
#: netbox/dcim/tables/devices.py:248 #: netbox/dcim/tables/devices.py:240
msgid "Power outlets" msgid "Power outlets"
msgstr "" msgstr ""
#: netbox/dcim/tables/devices.py:251 netbox/dcim/tables/devices.py:1064 #: netbox/dcim/tables/devices.py:243 netbox/dcim/tables/devices.py:1046
#: netbox/dcim/tables/devicetypes.py:125 netbox/dcim/views.py:1006 #: netbox/dcim/tables/devicetypes.py:125 netbox/dcim/views.py:1006
#: netbox/dcim/views.py:1245 netbox/dcim/views.py:1931 #: netbox/dcim/views.py:1245 netbox/dcim/views.py:1931
#: netbox/netbox/navigation/menu.py:81 netbox/netbox/navigation/menu.py:237 #: netbox/netbox/navigation/menu.py:81 netbox/netbox/navigation/menu.py:237
@ -6071,28 +6071,28 @@ msgstr ""
msgid "Interfaces" msgid "Interfaces"
msgstr "" msgstr ""
#: netbox/dcim/tables/devices.py:254 #: netbox/dcim/tables/devices.py:246
msgid "Front ports" msgid "Front ports"
msgstr "" msgstr ""
#: netbox/dcim/tables/devices.py:260 #: netbox/dcim/tables/devices.py:252
msgid "Device bays" msgid "Device bays"
msgstr "" msgstr ""
#: netbox/dcim/tables/devices.py:263 #: netbox/dcim/tables/devices.py:255
msgid "Module bays" msgid "Module bays"
msgstr "" msgstr ""
#: netbox/dcim/tables/devices.py:266 #: netbox/dcim/tables/devices.py:258
msgid "Inventory items" msgid "Inventory items"
msgstr "" msgstr ""
#: netbox/dcim/tables/devices.py:305 netbox/dcim/tables/modules.py:56 #: netbox/dcim/tables/devices.py:297 netbox/dcim/tables/modules.py:56
#: netbox/templates/dcim/modulebay.html:17 #: netbox/templates/dcim/modulebay.html:17
msgid "Module Bay" msgid "Module Bay"
msgstr "" msgstr ""
#: netbox/dcim/tables/devices.py:318 netbox/dcim/tables/devicetypes.py:48 #: netbox/dcim/tables/devices.py:310 netbox/dcim/tables/devicetypes.py:48
#: netbox/dcim/tables/devicetypes.py:140 netbox/dcim/views.py:1081 #: netbox/dcim/tables/devicetypes.py:140 netbox/dcim/views.py:1081
#: netbox/dcim/views.py:2024 netbox/netbox/navigation/menu.py:90 #: netbox/dcim/views.py:2024 netbox/netbox/navigation/menu.py:90
#: netbox/templates/dcim/device/base.html:52 #: netbox/templates/dcim/device/base.html:52
@ -6103,27 +6103,27 @@ msgstr ""
msgid "Inventory Items" msgid "Inventory Items"
msgstr "" msgstr ""
#: netbox/dcim/tables/devices.py:330 #: netbox/dcim/tables/devices.py:322
msgid "Cable Color" msgid "Cable Color"
msgstr "" msgstr ""
#: netbox/dcim/tables/devices.py:336 #: netbox/dcim/tables/devices.py:328
msgid "Link Peers" msgid "Link Peers"
msgstr "" msgstr ""
#: netbox/dcim/tables/devices.py:339 #: netbox/dcim/tables/devices.py:331
msgid "Mark Connected" msgid "Mark Connected"
msgstr "" msgstr ""
#: netbox/dcim/tables/devices.py:455 #: netbox/dcim/tables/devices.py:449
msgid "Maximum draw (W)" msgid "Maximum draw (W)"
msgstr "" msgstr ""
#: netbox/dcim/tables/devices.py:458 #: netbox/dcim/tables/devices.py:452
msgid "Allocated draw (W)" msgid "Allocated draw (W)"
msgstr "" msgstr ""
#: netbox/dcim/tables/devices.py:558 netbox/ipam/forms/model_forms.py:747 #: netbox/dcim/tables/devices.py:546 netbox/ipam/forms/model_forms.py:747
#: netbox/ipam/tables/fhrp.py:28 netbox/ipam/views.py:602 #: netbox/ipam/tables/fhrp.py:28 netbox/ipam/views.py:602
#: netbox/ipam/views.py:701 netbox/netbox/navigation/menu.py:145 #: netbox/ipam/views.py:701 netbox/netbox/navigation/menu.py:145
#: netbox/netbox/navigation/menu.py:147 #: netbox/netbox/navigation/menu.py:147
@ -6135,12 +6135,12 @@ msgstr ""
msgid "IP Addresses" msgid "IP Addresses"
msgstr "" msgstr ""
#: netbox/dcim/tables/devices.py:564 netbox/netbox/navigation/menu.py:189 #: netbox/dcim/tables/devices.py:552 netbox/netbox/navigation/menu.py:189
#: netbox/templates/ipam/inc/panels/fhrp_groups.html:6 #: netbox/templates/ipam/inc/panels/fhrp_groups.html:6
msgid "FHRP Groups" msgid "FHRP Groups"
msgstr "" msgstr ""
#: netbox/dcim/tables/devices.py:576 netbox/templates/dcim/interface.html:89 #: netbox/dcim/tables/devices.py:564 netbox/templates/dcim/interface.html:89
#: netbox/templates/virtualization/vminterface.html:67 #: netbox/templates/virtualization/vminterface.html:67
#: netbox/templates/vpn/tunnel.html:18 #: netbox/templates/vpn/tunnel.html:18
#: netbox/templates/vpn/tunneltermination.html:13 #: netbox/templates/vpn/tunneltermination.html:13
@ -6151,37 +6151,37 @@ msgstr ""
msgid "Tunnel" msgid "Tunnel"
msgstr "" msgstr ""
#: netbox/dcim/tables/devices.py:601 netbox/dcim/tables/devicetypes.py:224 #: netbox/dcim/tables/devices.py:589 netbox/dcim/tables/devicetypes.py:224
#: netbox/templates/dcim/interface.html:65 #: netbox/templates/dcim/interface.html:65
msgid "Management Only" msgid "Management Only"
msgstr "" msgstr ""
#: netbox/dcim/tables/devices.py:619 #: netbox/dcim/tables/devices.py:607
msgid "VDCs" msgid "VDCs"
msgstr "" msgstr ""
#: netbox/dcim/tables/devices.py:870 netbox/templates/dcim/modulebay.html:49 #: netbox/dcim/tables/devices.py:852 netbox/templates/dcim/modulebay.html:49
msgid "Installed Module" msgid "Installed Module"
msgstr "" msgstr ""
#: netbox/dcim/tables/devices.py:873 #: netbox/dcim/tables/devices.py:855
msgid "Module Serial" msgid "Module Serial"
msgstr "" msgstr ""
#: netbox/dcim/tables/devices.py:877 #: netbox/dcim/tables/devices.py:859
msgid "Module Asset Tag" msgid "Module Asset Tag"
msgstr "" msgstr ""
#: netbox/dcim/tables/devices.py:886 #: netbox/dcim/tables/devices.py:868
msgid "Module Status" msgid "Module Status"
msgstr "" msgstr ""
#: netbox/dcim/tables/devices.py:928 netbox/dcim/tables/devicetypes.py:308 #: netbox/dcim/tables/devices.py:910 netbox/dcim/tables/devicetypes.py:308
#: netbox/templates/dcim/inventoryitem.html:40 #: netbox/templates/dcim/inventoryitem.html:40
msgid "Component" msgid "Component"
msgstr "" msgstr ""
#: netbox/dcim/tables/devices.py:983 #: netbox/dcim/tables/devices.py:965
msgid "Items" msgid "Items"
msgstr "" msgstr ""
@ -6740,42 +6740,42 @@ msgstr ""
msgid "Invalid format. URL parameters must be passed as a dictionary." msgid "Invalid format. URL parameters must be passed as a dictionary."
msgstr "" msgstr ""
#: netbox/extras/dashboard/widgets.py:283 #: netbox/extras/dashboard/widgets.py:284
msgid "RSS Feed" msgid "RSS Feed"
msgstr "" msgstr ""
#: netbox/extras/dashboard/widgets.py:288 #: netbox/extras/dashboard/widgets.py:289
msgid "Embed an RSS feed from an external website." msgid "Embed an RSS feed from an external website."
msgstr "" msgstr ""
#: netbox/extras/dashboard/widgets.py:295 #: netbox/extras/dashboard/widgets.py:296
msgid "Feed URL" msgid "Feed URL"
msgstr "" msgstr ""
#: netbox/extras/dashboard/widgets.py:300 #: netbox/extras/dashboard/widgets.py:301
msgid "The maximum number of objects to display" msgid "The maximum number of objects to display"
msgstr "" msgstr ""
#: netbox/extras/dashboard/widgets.py:305 #: netbox/extras/dashboard/widgets.py:306
msgid "How long to stored the cached content (in seconds)" msgid "How long to stored the cached content (in seconds)"
msgstr "" msgstr ""
#: netbox/extras/dashboard/widgets.py:357 netbox/templates/account/base.html:10 #: netbox/extras/dashboard/widgets.py:358 netbox/templates/account/base.html:10
#: netbox/templates/account/bookmarks.html:7 #: netbox/templates/account/bookmarks.html:7
#: netbox/templates/inc/user_menu.html:30 #: netbox/templates/inc/user_menu.html:30
msgid "Bookmarks" msgid "Bookmarks"
msgstr "" msgstr ""
#: netbox/extras/dashboard/widgets.py:361 #: netbox/extras/dashboard/widgets.py:362
msgid "Show your personal bookmarks" msgid "Show your personal bookmarks"
msgstr "" msgstr ""
#: netbox/extras/events.py:128 #: netbox/extras/events.py:134
#, python-brace-format #, python-brace-format
msgid "Unknown action type for an event rule: {action_type}" msgid "Unknown action type for an event rule: {action_type}"
msgstr "" msgstr ""
#: netbox/extras/events.py:176 #: netbox/extras/events.py:182
#, python-brace-format #, python-brace-format
msgid "Cannot import events pipeline {name} error: {error}" msgid "Cannot import events pipeline {name} error: {error}"
msgstr "" msgstr ""
@ -7385,7 +7385,7 @@ msgstr ""
msgid "request ID" msgid "request ID"
msgstr "" msgstr ""
#: netbox/extras/models/change_logging.py:52 netbox/extras/models/staging.py:69 #: netbox/extras/models/change_logging.py:52 netbox/extras/models/staging.py:70
msgid "action" msgid "action"
msgstr "" msgstr ""
@ -8096,19 +8096,19 @@ msgstr ""
msgid "cached values" msgid "cached values"
msgstr "" msgstr ""
#: netbox/extras/models/staging.py:44 #: netbox/extras/models/staging.py:45
msgid "branch" msgid "branch"
msgstr "" msgstr ""
#: netbox/extras/models/staging.py:45 #: netbox/extras/models/staging.py:46
msgid "branches" msgid "branches"
msgstr "" msgstr ""
#: netbox/extras/models/staging.py:97 #: netbox/extras/models/staging.py:98
msgid "staged change" msgid "staged change"
msgstr "" msgstr ""
#: netbox/extras/models/staging.py:98 #: netbox/extras/models/staging.py:99
msgid "staged changes" msgid "staged changes"
msgstr "" msgstr ""
@ -8156,7 +8156,7 @@ msgstr ""
msgid "Database changes have been reverted due to error." msgid "Database changes have been reverted due to error."
msgstr "" msgstr ""
#: netbox/extras/signals.py:146 #: netbox/extras/signals.py:133
#, python-brace-format #, python-brace-format
msgid "Deletion is prevented by a protection rule: {message}" msgid "Deletion is prevented by a protection rule: {message}"
msgstr "" msgstr ""
@ -8937,7 +8937,7 @@ msgstr ""
#: netbox/virtualization/forms/filtersets.py:238 #: netbox/virtualization/forms/filtersets.py:238
#: netbox/virtualization/forms/model_forms.py:220 #: netbox/virtualization/forms/model_forms.py:220
#: netbox/virtualization/tables/virtualmachines.py:128 #: netbox/virtualization/tables/virtualmachines.py:128
#: netbox/virtualization/tables/virtualmachines.py:181 netbox/vpn/choices.py:45 #: netbox/virtualization/tables/virtualmachines.py:183 netbox/vpn/choices.py:45
#: netbox/vpn/forms/filtersets.py:293 netbox/vpn/forms/model_forms.py:160 #: netbox/vpn/forms/filtersets.py:293 netbox/vpn/forms/model_forms.py:160
#: netbox/vpn/forms/model_forms.py:171 netbox/vpn/forms/model_forms.py:273 #: netbox/vpn/forms/model_forms.py:171 netbox/vpn/forms/model_forms.py:273
#: netbox/vpn/forms/model_forms.py:454 #: netbox/vpn/forms/model_forms.py:454

View File

@ -493,10 +493,18 @@ class APIViewTestCases:
def _build_filtered_query(self, name, **filters): def _build_filtered_query(self, name, **filters):
""" """
Create a filtered query: i.e. ip_address_list(filters: {address: "1.1.1.1/24"}){. Create a filtered query: i.e. device_list(filters: {name: {i_contains: "akron"}}){.
""" """
# TODO: This should be extended to support AND, OR multi-lookups
if filters: if filters:
filter_string = ', '.join(f'{k}: "{v}"' for k, v in filters.items()) for field_name, params in filters.items():
lookup = params['lookup']
value = params['value']
if lookup:
query = f'{{{lookup}: "{value}"}}'
filter_string = f'{field_name}: {query}'
else:
filter_string = f'{field_name}: "{value}"'
filter_string = f'(filters: {{{filter_string}}})' filter_string = f'(filters: {{{filter_string}}})'
else: else:
filter_string = '' filter_string = ''

View File

@ -173,6 +173,8 @@ class VirtualMachineVMInterfaceTable(VMInterfaceTable):
default_columns = ('pk', 'name', 'enabled', 'mac_address', 'mtu', 'mode', 'description', 'ip_addresses') default_columns = ('pk', 'name', 'enabled', 'mac_address', 'mtu', 'mode', 'description', 'ip_addresses')
row_attrs = { row_attrs = {
'data-name': lambda record: record.name, 'data-name': lambda record: record.name,
'data-virtual': lambda record: "true",
'data-enabled': lambda record: "true" if record.enabled else "false",
} }