diff --git a/.github/workflows/close-stale-issues.yml b/.github/workflows/close-stale-issues.yml index 29f28fddf..1e0e193df 100644 --- a/.github/workflows/close-stale-issues.yml +++ b/.github/workflows/close-stale-issues.yml @@ -18,7 +18,7 @@ jobs: - uses: actions/stale@v9 with: # General parameters - operations-per-run: 100 + operations-per-run: 200 remove-stale-when-updated: false # Issue parameters @@ -43,7 +43,7 @@ jobs: # Pull request parameters close-pr-message: > This PR has been automatically closed due to lack of activity. - days-before-pr-stale: 15 + days-before-pr-stale: 30 days-before-pr-close: 15 exempt-pr-labels: 'status: blocked' stale-pr-label: 'pending closure' diff --git a/netbox/core/management/commands/nbshell.py b/netbox/core/management/commands/nbshell.py index e26f956c8..8f729d10a 100644 --- a/netbox/core/management/commands/nbshell.py +++ b/netbox/core/management/commands/nbshell.py @@ -11,6 +11,10 @@ from core.models import ObjectType from users.models import User APPS = ('circuits', 'core', 'dcim', 'extras', 'ipam', 'tenancy', 'users', 'virtualization', 'vpn', 'wireless') +EXCLUDE_MODELS = ( + 'extras.branch', + 'extras.stagedchange', +) BANNER_TEXT = """### NetBox interactive shell ({node}) ### Python {python} | Django {django} | NetBox {netbox} @@ -44,12 +48,16 @@ class Command(BaseCommand): # Gather Django models and constants from each app for app in APPS: - self.django_models[app] = [] + models = [] # Load models from each app for model in apps.get_app_config(app).get_models(): - namespace[model.__name__] = model - self.django_models[app].append(model.__name__) + app_label = model._meta.app_label + model_name = model._meta.model_name + if f'{app_label}.{model_name}' not in EXCLUDE_MODELS: + namespace[model.__name__] = model + models.append(model.__name__) + self.django_models[app] = sorted(models) # Constants try: diff --git a/netbox/dcim/choices.py b/netbox/dcim/choices.py index 127655ba7..c90a0b3ea 100644 --- a/netbox/dcim/choices.py +++ b/netbox/dcim/choices.py @@ -684,6 +684,7 @@ class PowerOutletTypeChoices(ChoiceSet): # Direct current (DC) TYPE_DC = 'dc-terminal' # Proprietary + TYPE_EATON_C39 = 'eaton-c39' TYPE_HDOT_CX = 'hdot-cx' TYPE_SAF_D_GRID = 'saf-d-grid' TYPE_NEUTRIK_POWERCON_20A = 'neutrik-powercon-20a' @@ -805,6 +806,7 @@ class PowerOutletTypeChoices(ChoiceSet): (TYPE_DC, 'DC Terminal'), )), (_('Proprietary'), ( + (TYPE_EATON_C39, 'Eaton C39'), (TYPE_HDOT_CX, 'HDOT Cx'), (TYPE_SAF_D_GRID, 'Saf-D-Grid'), (TYPE_NEUTRIK_POWERCON_20A, 'Neutrik powerCON (20A)'), diff --git a/netbox/extras/models/customfields.py b/netbox/extras/models/customfields.py index 7a0a08614..889594902 100644 --- a/netbox/extras/models/customfields.py +++ b/netbox/extras/models/customfields.py @@ -294,11 +294,11 @@ class CustomField(CloningMixin, ExportTemplatesMixin, ChangeLoggedModel): no longer assigned to a model, or because it has been deleted). """ for ct in content_types: - model = ct.model_class() - instances = model.objects.filter(custom_field_data__has_key=self.name) - for instance in instances: - del instance.custom_field_data[self.name] - model.objects.bulk_update(instances, ['custom_field_data'], batch_size=100) + if model := ct.model_class(): + instances = model.objects.filter(custom_field_data__has_key=self.name) + for instance in instances: + del instance.custom_field_data[self.name] + model.objects.bulk_update(instances, ['custom_field_data'], batch_size=100) def rename_object_data(self, old_name, new_name): """ diff --git a/netbox/netbox/api/serializers/fields.py b/netbox/netbox/api/serializers/fields.py index 4fee36043..74782bddf 100644 --- a/netbox/netbox/api/serializers/fields.py +++ b/netbox/netbox/api/serializers/fields.py @@ -1,5 +1,8 @@ +from django.utils.translation import gettext_lazy as _ from rest_framework import serializers +from utilities.views import get_viewname + __all__ = ( 'NetBoxAPIHyperlinkedIdentityField', 'NetBoxURLHyperlinkedIdentityField', @@ -30,12 +33,10 @@ class BaseNetBoxHyperlinkedIdentityField(serializers.HyperlinkedIdentityField): lookup_value = getattr(obj, self.lookup_field) kwargs = {self.lookup_url_kwarg: lookup_value} - model_name = self.parent.Meta.model._meta.model_name - app_name = self.parent.Meta.model._meta.app_label - view_name = self.get_view_name(app_name, model_name) + view_name = self.get_view_name(obj) return self.reverse(view_name, kwargs=kwargs, request=request, format=format) - def get_view_name(self, app_name, model_name): + def get_view_name(self, model): raise NotImplementedError(_('{class_name} must implement get_view_name()').format( class_name=self.__class__.__name__ )) @@ -43,11 +44,11 @@ class BaseNetBoxHyperlinkedIdentityField(serializers.HyperlinkedIdentityField): class NetBoxAPIHyperlinkedIdentityField(BaseNetBoxHyperlinkedIdentityField): - def get_view_name(self, app_name, model_name): - return f'{app_name}-api:{model_name}-detail' + def get_view_name(self, model): + return get_viewname(model=model, action='detail', rest_api=True) class NetBoxURLHyperlinkedIdentityField(BaseNetBoxHyperlinkedIdentityField): - def get_view_name(self, app_name, model_name): - return f'{app_name}:{model_name}' + def get_view_name(self, model): + return get_viewname(model=model) diff --git a/netbox/project-static/dist/netbox.css b/netbox/project-static/dist/netbox.css index 762cafd5d..f1b9e24e2 100644 Binary files a/netbox/project-static/dist/netbox.css and b/netbox/project-static/dist/netbox.css differ diff --git a/netbox/project-static/package.json b/netbox/project-static/package.json index acc6803b6..5c16bee60 100644 --- a/netbox/project-static/package.json +++ b/netbox/project-static/package.json @@ -24,7 +24,7 @@ "dependencies": { "@fontsource-variable/plus-jakarta-sans": "^5.1.0", "@mdi/font": "7.4.47", - "@tabler/core": "1.0.0-beta20", + "@tabler/core": "1.0.0-beta21", "bootstrap": "5.3.3", "clipboard": "2.0.11", "flatpickr": "4.6.13", diff --git a/netbox/project-static/yarn.lock b/netbox/project-static/yarn.lock index bc1f541b2..ca9f5ff96 100644 --- a/netbox/project-static/yarn.lock +++ b/netbox/project-static/yarn.lock @@ -675,19 +675,19 @@ resolved "https://registry.yarnpkg.com/@rtsao/scc/-/scc-1.1.0.tgz#927dd2fae9bc3361403ac2c7a00c32ddce9ad7e8" integrity sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g== -"@tabler/core@1.0.0-beta20": - version "1.0.0-beta20" - resolved "https://registry.yarnpkg.com/@tabler/core/-/core-1.0.0-beta20.tgz#3fcc3b5634ca89a413ba9c077df7bdfc531ab93c" - integrity sha512-OzKpur+Ug7e+HMbNJrMcSuWZGUsJTvu7HYboBNRE8qyo1RKIWqvwL5YewKBJ+odW5pDOqBPzbsS4je3EBQQxHw== +"@tabler/core@1.0.0-beta21": + version "1.0.0-beta21" + resolved "https://registry.yarnpkg.com/@tabler/core/-/core-1.0.0-beta21.tgz#cd10d7648b3b7b31927a430fd776d3304e796403" + integrity sha512-9ZKu38BScc0eHruhX/SlVDSiXenBFSgBp2WDq6orkuC8J/1yutKDt7CdXuJpBwkiADEk5yqYV31Ku+CnhwOc3Q== dependencies: "@popperjs/core" "^2.11.8" - "@tabler/icons" "^2.32.0" - bootstrap "5.3.1" + "@tabler/icons" "^3.14.0" + bootstrap "5.3.3" -"@tabler/icons@^2.32.0": - version "2.47.0" - resolved "https://registry.yarnpkg.com/@tabler/icons/-/icons-2.47.0.tgz#c41c680d1947e3ab2d60af3febc4132287c60596" - integrity sha512-4w5evLh+7FUUiA1GucvGj2ReX2TvOjEr4ejXdwL/bsjoSkof6r1gQmzqI+VHrE2CpJpB3al7bCTulOkFa/RcyA== +"@tabler/icons@^3.14.0": + version "3.16.0" + resolved "https://registry.yarnpkg.com/@tabler/icons/-/icons-3.16.0.tgz#d618670b80163925a31a6c2290e8775f6058d81a" + integrity sha512-GU7MSx4uQEr55BmyON6hD/QYTl6k1v0YlRhM91gBWDoKAbyCt6QIYw7rpJ/ecdh5zrHaTOJKPenZ4+luoutwFA== "@tanstack/react-virtual@^3.0.0-beta.60": version "3.5.0" @@ -977,11 +977,6 @@ binary-extensions@^2.0.0: resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== -bootstrap@5.3.1: - version "5.3.1" - resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-5.3.1.tgz#8ca07040ad15d7f75891d1504cf14c5dedfb1cfe" - integrity sha512-jzwza3Yagduci2x0rr9MeFSORjcHpt0lRZukZPZQJT1Dth5qzV7XcgGqYzi39KGAVYR8QEDVoO0ubFKOxzMG+g== - bootstrap@5.3.3: version "5.3.3" resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-5.3.3.tgz#de35e1a765c897ac940021900fcbb831602bac38"