diff --git a/docs/administration/authentication/google.md b/docs/administration/authentication/google.md new file mode 100644 index 000000000..456f3a457 --- /dev/null +++ b/docs/administration/authentication/google.md @@ -0,0 +1,52 @@ +# Google + +This guide explains how to configure single sign-on (SSO) support for NetBox using [Google OAuth2](https://developers.google.com/identity/protocols/oauth2/web-server) as an authentication backend. + +## Google OAuth2 Configuration + +1. Log into [console.cloud.google.com](https://console.cloud.google.com/). +2. Create new project for NetBox. +3. Under "APIs and Services" click "OAuth consent screen" and enter the required information. +4. Under "Credentials," click "Create Credentials" and select "OAuth 2.0 Client ID." Select type "Web application." + - "Authorized JavaScript origins" should follow the format `http[s]://[:]` + - "Authorized redirect URIs" should follow the format `http[s]://[:]/oauth/complete/google-oauth2/` +5. Copy the "Client ID" and "Client Secret" values somewhere convenient. + +!!! note + Google requires the NetBox hostname to use a public top-level-domain (e.g. `.com`, `.net`). The use of IP addresses is not permitted (except `127.0.0.1`). + +For more information, consult [Google's documentation](https://developers.google.com/identity/protocols/oauth2/web-server#prerequisites). + +## NetBox Configuration + +### 1. Enter configuration parameters + +Enter the following configuration parameters in `configuration.py`, substituting your own values: + +```python +REMOTE_AUTH_BACKEND = 'social_core.backends.google.GoogleOAuth2' +SOCIAL_AUTH_GOOGLE_OAUTH2_KEY = '{CLIENT_ID}' +SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET = '{CLIENT_SECRET}' +``` + +### 2. Restart NetBox + +Restart the NetBox services so that the new configuration takes effect. This is typically done with the command below: + +```no-highlight +sudo systemctl restart netbox +``` + +## Testing + +Log out of NetBox if already authenticated, and click the "Log In" button at top right. You should see the normal login form as well as an option to authenticate using Google. Click that link. + +![NetBox Google login form](../../media/authentication/netbox_google_login.png) + +You should be redirected to Google's authentication portal. Enter the username/email and password of your test account to continue. You may also be prompted to grant this application access to your account. + +![NetBox Google login form](../../media/authentication/google_login_portal.png) + +If successful, you will be redirected back to the NetBox UI, and will be logged in as the Google user. You can verify this by navigating to your profile (using the button at top right). + +This user account has been replicated locally to NetBox, and can now be assigned groups and permissions. diff --git a/docs/administration/authentication/microsoft-entra-id.md b/docs/administration/authentication/microsoft-entra-id.md index 3451c656f..b44499fbe 100644 --- a/docs/administration/authentication/microsoft-entra-id.md +++ b/docs/administration/authentication/microsoft-entra-id.md @@ -16,7 +16,7 @@ Under the Azure Active Directory dashboard, navigate to **Add > App registration Enter a name for the registration (e.g. "NetBox") and ensure that the "single tenant" option is selected. -Under "Redirect URI", select "Web" for the platform and enter the path to your NetBox installation, ending with `/oauth/complete/entraid-oauth2/`. Note that this URI **must** begin with `https://` unless you are referencing localhost (for development purposes). +Under "Redirect URI", select "Web" for the platform and enter the path to your NetBox installation, ending with `/oauth/complete/azuread-oauth2/`. Note that this URI **must** begin with `https://` unless you are referencing localhost (for development purposes). ![App registration parameters](../../media/authentication/azure_ad_app_registration.png) diff --git a/docs/customization/custom-scripts.md b/docs/customization/custom-scripts.md index 3fa6491d2..1051b31f6 100644 --- a/docs/customization/custom-scripts.md +++ b/docs/customization/custom-scripts.md @@ -72,6 +72,9 @@ script_order = (MyCustomScript, AnotherCustomScript) Script attributes are defined under a class named `Meta` within the script. These are optional, but encouraged. +!!! warning + These are also defined and used as properties on the base custom script class, so don't use the same names as variables or override them in your custom script. + ### `name` This is the human-friendly names of your script. If omitted, the class name will be used. diff --git a/docs/development/style-guide.md b/docs/development/style-guide.md index 0d4caf395..9d6630de0 100644 --- a/docs/development/style-guide.md +++ b/docs/development/style-guide.md @@ -76,4 +76,4 @@ When adding a new dependency, a short description of the package and the URL of * When referring to NetBox in writing, use the proper form "NetBox," with the letters N and B capitalized. The lowercase form "netbox" should be used in code, filenames, etc. but never "Netbox" or any other deviation. -* There is an SVG form of the NetBox logo at [docs/netbox_logo.svg](../netbox_logo.svg). It is preferred to use this logo for all purposes as it scales to arbitrary sizes without loss of resolution. If a raster image is required, the SVG logo should be converted to a PNG image of the prescribed size. +* There are SVG forms of the NetBox logo for both [light mode](../netbox_logo_light.svg) and [dark mode](../netbox_logo_dark.svg) available. It is preferred to use the SVG logo for all purposes as it scales to arbitrary sizes without loss of resolution. If a raster image is required, the SVG logo should be converted to a PNG image of the desired size. diff --git a/docs/extra.css b/docs/extra.css index e953fa14c..4b8cd87fe 100644 --- a/docs/extra.css +++ b/docs/extra.css @@ -5,6 +5,10 @@ img { margin-right: auto; } +.md-content img { + background-color: rgba(255, 255, 255, 0.64); +} + /* Tables */ table { margin-bottom: 24px; diff --git a/docs/index.md b/docs/index.md index 5ef650ca6..a79ab03b4 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,4 +1,5 @@ -![NetBox](netbox_logo.svg "NetBox logo"){style="height: 100px; margin-bottom: 3em"} +![NetBox](netbox_logo_light.svg#only-light "NetBox logo"){style="height: 100px; margin-bottom: 3em; background: none;"} +![NetBox](netbox_logo_dark.svg#only-dark "NetBox logo"){style="height: 100px; margin-bottom: 3em; background: none;"} # The Premier Network Source of Truth diff --git a/docs/media/authentication/google_login_portal.png b/docs/media/authentication/google_login_portal.png new file mode 100644 index 000000000..55eefd872 Binary files /dev/null and b/docs/media/authentication/google_login_portal.png differ diff --git a/docs/media/authentication/netbox_google_login.png b/docs/media/authentication/netbox_google_login.png new file mode 100644 index 000000000..730173b5d Binary files /dev/null and b/docs/media/authentication/netbox_google_login.png differ diff --git a/docs/netbox_logo_dark.svg b/docs/netbox_logo_dark.svg new file mode 100644 index 000000000..958a1d401 --- /dev/null +++ b/docs/netbox_logo_dark.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/netbox_logo.svg b/docs/netbox_logo_light.svg similarity index 100% rename from docs/netbox_logo.svg rename to docs/netbox_logo_light.svg diff --git a/docs/release-notes/version-4.1.md b/docs/release-notes/version-4.1.md index d48bb899f..c29fb3aab 100644 --- a/docs/release-notes/version-4.1.md +++ b/docs/release-notes/version-4.1.md @@ -1,5 +1,17 @@ # NetBox v4.1 +## v4.1.5 (FUTURE) + +### Bug Fixes + +* [#17710](https://github.com/netbox-community/netbox/issues/17710) - Remove cached fields on CableTermination model from GraphQL API +* [#17740](https://github.com/netbox-community/netbox/issues/17740) - Ensure support for image attachments with a `.webp` file extension +* [#17749](https://github.com/netbox-community/netbox/issues/17749) - Restore missing `devicetypes` and `children` fields for several objects in GraphQL API +* [#17754](https://github.com/netbox-community/netbox/issues/17754) - Remove paginator from version history table under plugin view +* [#17759](https://github.com/netbox-community/netbox/issues/17759) - Retain `job_timeout` value when scheduling a recurring custom script + +--- + ## v4.1.4 (2024-10-15) ### Enhancements diff --git a/mkdocs.yml b/mkdocs.yml index 94a4edcb3..00e03a4ce 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -156,6 +156,7 @@ nav: - Administration: - Authentication: - Overview: 'administration/authentication/overview.md' + - Google: 'administration/authentication/google.md' - Microsoft Entra ID: 'administration/authentication/microsoft-entra-id.md' - Okta: 'administration/authentication/okta.md' - Permissions: 'administration/permissions.md' diff --git a/netbox/dcim/graphql/types.py b/netbox/dcim/graphql/types.py index b951aead0..cd863837a 100644 --- a/netbox/dcim/graphql/types.py +++ b/netbox/dcim/graphql/types.py @@ -112,7 +112,7 @@ class ModularComponentTemplateType(ComponentTemplateType): @strawberry_django.type( models.CableTermination, - exclude=('termination_type', 'termination_id'), + exclude=('termination_type', 'termination_id', '_device', '_rack', '_location', '_site'), filters=CableTerminationFilter ) class CableTerminationType(NetBoxObjectType): @@ -243,6 +243,7 @@ class DeviceType(ConfigContextMixin, ImageAttachmentsMixin, ContactsMixin, NetBo consoleserverports: List[Annotated["ConsoleServerPortType", strawberry.lazy('dcim.graphql.types')]] poweroutlets: List[Annotated["PowerOutletType", strawberry.lazy('dcim.graphql.types')]] frontports: List[Annotated["FrontPortType", strawberry.lazy('dcim.graphql.types')]] + devicebays: List[Annotated["DeviceBayType", strawberry.lazy('dcim.graphql.types')]] modulebays: List[Annotated["ModuleBayType", strawberry.lazy('dcim.graphql.types')]] services: List[Annotated["ServiceType", strawberry.lazy('ipam.graphql.types')]] inventoryitems: List[Annotated["InventoryItemType", strawberry.lazy('dcim.graphql.types')]] diff --git a/netbox/extras/jobs.py b/netbox/extras/jobs.py index 64a7d6a69..a913fe456 100644 --- a/netbox/extras/jobs.py +++ b/netbox/extras/jobs.py @@ -49,7 +49,6 @@ class ScriptJob(JobRunner): script.log_info(message=_("Database changes have been reverted automatically.")) if script.failed: logger.warning("Script failed") - raise except Exception as e: if type(e) is AbortScript: diff --git a/netbox/extras/utils.py b/netbox/extras/utils.py index 28d2e13f0..efe7ada5b 100644 --- a/netbox/extras/utils.py +++ b/netbox/extras/utils.py @@ -33,7 +33,7 @@ def image_upload(instance, filename): # Rename the file to the provided name, if any. Attempt to preserve the file extension. extension = filename.rsplit('.')[-1].lower() - if instance.name and extension in ['bmp', 'gif', 'jpeg', 'jpg', 'png']: + if instance.name and extension in ['bmp', 'gif', 'jpeg', 'jpg', 'png', 'webp']: filename = '.'.join([instance.name, extension]) elif instance.name: filename = instance.name diff --git a/netbox/netbox/authentication/__init__.py b/netbox/netbox/authentication/__init__.py index f80454f99..7c2df4200 100644 --- a/netbox/netbox/authentication/__init__.py +++ b/netbox/netbox/authentication/__init__.py @@ -20,10 +20,10 @@ AUTH_BACKEND_ATTRS = { 'amazon': ('Amazon AWS', 'aws'), 'apple': ('Apple', 'apple'), 'auth0': ('Auth0', None), - 'entraid-oauth2': ('Microsoft Entra ID', 'microsoft'), - 'entraid-b2c-oauth2': ('Microsoft Entra ID', 'microsoft'), - 'entraid-tenant-oauth2': ('Microsoft Entra ID', 'microsoft'), - 'entraid-v2-tenant-oauth2': ('Microsoft Entra ID', 'microsoft'), + 'azuread-oauth2': ('Microsoft Entra ID', 'microsoft'), + 'azuread-b2c-oauth2': ('Microsoft Entra ID', 'microsoft'), + 'azuread-tenant-oauth2': ('Microsoft Entra ID', 'microsoft'), + 'azuread-v2-tenant-oauth2': ('Microsoft Entra ID', 'microsoft'), 'bitbucket': ('BitBucket', 'bitbucket'), 'bitbucket-oauth2': ('BitBucket', 'bitbucket'), 'digitalocean': ('DigitalOcean', 'digital-ocean'), diff --git a/netbox/netbox/jobs.py b/netbox/netbox/jobs.py index 087c24896..ae8f2f109 100644 --- a/netbox/netbox/jobs.py +++ b/netbox/netbox/jobs.py @@ -68,6 +68,8 @@ class JobRunner(ABC): finally: if job.interval: new_scheduled_time = (job.scheduled or job.started) + timedelta(minutes=job.interval) + if job.object and getattr(job.object, "python_class", None): + kwargs["job_timeout"] = job.object.python_class.job_timeout cls.enqueue( instance=job.object, user=job.user, diff --git a/netbox/project-static/dist/netbox.css b/netbox/project-static/dist/netbox.css index fbad302ff..cd66ffa0f 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/styles/custom/_markdown.scss b/netbox/project-static/styles/custom/_markdown.scss index 32ef7a09c..75ada3bc6 100644 --- a/netbox/project-static/styles/custom/_markdown.scss +++ b/netbox/project-static/styles/custom/_markdown.scss @@ -28,16 +28,19 @@ } -// Remove the bottom margin of

elements inside a table cell -td > .rendered-markdown { - max-height: 200px; - overflow-y: scroll; - +// Remove the bottom margin of the last

elements in markdown +.rendered-markdown { p:last-of-type { margin-bottom: 0; } } +// fix layout of rendered markdown inside a table cell +td > .rendered-markdown { + max-height: 200px; + overflow-y: scroll; +} + // Markdown preview .markdown-widget { .preview { diff --git a/netbox/project-static/styles/overrides/_tabler.scss b/netbox/project-static/styles/overrides/_tabler.scss index 252da8f4a..6f7c7cc8c 100644 --- a/netbox/project-static/styles/overrides/_tabler.scss +++ b/netbox/project-static/styles/overrides/_tabler.scss @@ -131,6 +131,11 @@ body[data-bs-theme=dark] { .toast { color: var(--#{$prefix}body-color); } + .table-primary { + --tblr-table-bg: rgba(var(--tblr-secondary-rgb), 0.48); + --tblr-table-hover-bg: inherit; + --tblr-table-hover-color: inherit; + } } // Do not apply padding to elements inside a

diff --git a/netbox/templates/core/plugin.html b/netbox/templates/core/plugin.html
index 34eaf81ee..b833db037 100644
--- a/netbox/templates/core/plugin.html
+++ b/netbox/templates/core/plugin.html
@@ -2,6 +2,7 @@
 {% load helpers %}
 {% load form_helpers %}
 {% load i18n %}
+{% load render_table from django_tables2 %}
 
 {% block title %}{{ plugin.title_long }}{% endblock %}
 
@@ -93,8 +94,8 @@
       

{% trans "Version History" %}

-
- {% include 'htmx/table.html' %} +
+ {% render_table table 'inc/table.html' %}
diff --git a/netbox/templates/dcim/component_list.html b/netbox/templates/dcim/component_list.html index 6351643e8..6f91aff3e 100644 --- a/netbox/templates/dcim/component_list.html +++ b/netbox/templates/dcim/component_list.html @@ -10,7 +10,7 @@ {% endif %} {% if 'bulk_rename' in actions %} {% with bulk_rename_view=model|validated_viewname:"bulk_rename" %} - {% endwith %} diff --git a/netbox/templates/dcim/device_list.html b/netbox/templates/dcim/device_list.html index 41ef8fc73..493b652f5 100644 --- a/netbox/templates/dcim/device_list.html +++ b/netbox/templates/dcim/device_list.html @@ -78,7 +78,7 @@ {% if 'bulk_edit' in actions %}
{% bulk_edit_button model query_params=request.GET %} -
diff --git a/netbox/tenancy/graphql/types.py b/netbox/tenancy/graphql/types.py index 120b5c71b..7baa136b3 100644 --- a/netbox/tenancy/graphql/types.py +++ b/netbox/tenancy/graphql/types.py @@ -66,6 +66,7 @@ class TenantGroupType(OrganizationalObjectType): parent: Annotated["TenantGroupType", strawberry.lazy('tenancy.graphql.types')] | None tenants: List[TenantType] + children: List[Annotated["TenantGroupType", strawberry.lazy('tenancy.graphql.types')]] # @@ -99,6 +100,7 @@ class ContactGroupType(OrganizationalObjectType): parent: Annotated["ContactGroupType", strawberry.lazy('tenancy.graphql.types')] | None contacts: List[ContactType] + children: List[Annotated["ContactGroupType", strawberry.lazy('tenancy.graphql.types')]] @strawberry_django.type( diff --git a/netbox/translations/en/LC_MESSAGES/django.po b/netbox/translations/en/LC_MESSAGES/django.po index 44b7b82a0..4748feb46 100644 --- a/netbox/translations/en/LC_MESSAGES/django.po +++ b/netbox/translations/en/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-10-16 05:01+0000\n" +"POT-Creation-Date: 2024-10-18 05:01+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -212,14 +212,13 @@ msgstr "" #: netbox/dcim/tables/power.py:26 netbox/dcim/tables/power.py:93 #: netbox/dcim/tables/racks.py:122 netbox/dcim/tables/racks.py:207 #: netbox/dcim/tables/sites.py:134 netbox/extras/filtersets.py:525 -#: netbox/ipam/forms/bulk_edit.py:217 netbox/ipam/forms/bulk_edit.py:284 -#: netbox/ipam/forms/bulk_edit.py:451 netbox/ipam/forms/bulk_edit.py:529 -#: netbox/ipam/forms/bulk_import.py:171 netbox/ipam/forms/bulk_import.py:429 -#: netbox/ipam/forms/filtersets.py:153 netbox/ipam/forms/filtersets.py:231 -#: netbox/ipam/forms/filtersets.py:432 netbox/ipam/forms/filtersets.py:489 -#: netbox/ipam/forms/model_forms.py:205 netbox/ipam/forms/model_forms.py:636 -#: netbox/ipam/tables/ip.py:245 netbox/ipam/tables/vlans.py:118 -#: netbox/ipam/tables/vlans.py:221 +#: netbox/ipam/forms/bulk_edit.py:218 netbox/ipam/forms/bulk_edit.py:285 +#: netbox/ipam/forms/bulk_edit.py:484 netbox/ipam/forms/bulk_import.py:171 +#: netbox/ipam/forms/bulk_import.py:429 netbox/ipam/forms/filtersets.py:153 +#: netbox/ipam/forms/filtersets.py:231 netbox/ipam/forms/filtersets.py:432 +#: netbox/ipam/forms/filtersets.py:489 netbox/ipam/forms/model_forms.py:205 +#: netbox/ipam/forms/model_forms.py:636 netbox/ipam/tables/ip.py:245 +#: netbox/ipam/tables/vlans.py:118 netbox/ipam/tables/vlans.py:221 #: netbox/templates/circuits/inc/circuit_termination_fields.html:6 #: netbox/templates/dcim/device.html:22 #: netbox/templates/dcim/inc/cable_termination.html:8 @@ -415,13 +414,13 @@ msgstr "" #: netbox/extras/forms/bulk_edit.py:256 netbox/extras/forms/bulk_edit.py:274 #: netbox/extras/forms/bulk_edit.py:298 netbox/extras/forms/bulk_edit.py:312 #: netbox/extras/forms/bulk_edit.py:339 netbox/extras/tables/tables.py:79 -#: netbox/ipam/forms/bulk_edit.py:52 netbox/ipam/forms/bulk_edit.py:72 -#: netbox/ipam/forms/bulk_edit.py:92 netbox/ipam/forms/bulk_edit.py:116 -#: netbox/ipam/forms/bulk_edit.py:145 netbox/ipam/forms/bulk_edit.py:174 -#: netbox/ipam/forms/bulk_edit.py:193 netbox/ipam/forms/bulk_edit.py:275 -#: netbox/ipam/forms/bulk_edit.py:320 netbox/ipam/forms/bulk_edit.py:368 -#: netbox/ipam/forms/bulk_edit.py:411 netbox/ipam/forms/bulk_edit.py:427 -#: netbox/ipam/forms/bulk_edit.py:561 netbox/ipam/forms/bulk_edit.py:592 +#: netbox/ipam/forms/bulk_edit.py:53 netbox/ipam/forms/bulk_edit.py:73 +#: netbox/ipam/forms/bulk_edit.py:93 netbox/ipam/forms/bulk_edit.py:117 +#: netbox/ipam/forms/bulk_edit.py:146 netbox/ipam/forms/bulk_edit.py:175 +#: netbox/ipam/forms/bulk_edit.py:194 netbox/ipam/forms/bulk_edit.py:276 +#: netbox/ipam/forms/bulk_edit.py:321 netbox/ipam/forms/bulk_edit.py:369 +#: netbox/ipam/forms/bulk_edit.py:412 netbox/ipam/forms/bulk_edit.py:428 +#: netbox/ipam/forms/bulk_edit.py:516 netbox/ipam/forms/bulk_edit.py:547 #: netbox/templates/account/token.html:35 #: netbox/templates/circuits/circuit.html:59 #: netbox/templates/circuits/circuitgroup.html:32 @@ -430,7 +429,7 @@ msgstr "" #: netbox/templates/circuits/provider.html:33 #: netbox/templates/circuits/providernetwork.html:32 #: netbox/templates/core/datasource.html:54 -#: netbox/templates/core/plugin.html:79 netbox/templates/dcim/cable.html:36 +#: netbox/templates/core/plugin.html:80 netbox/templates/dcim/cable.html:36 #: netbox/templates/dcim/consoleport.html:44 #: netbox/templates/dcim/consoleserverport.html:44 #: netbox/templates/dcim/device.html:94 netbox/templates/dcim/devicebay.html:32 @@ -654,8 +653,8 @@ msgstr "" #: netbox/dcim/tables/devices.py:1063 netbox/dcim/tables/modules.py:69 #: netbox/dcim/tables/power.py:74 netbox/dcim/tables/racks.py:126 #: netbox/dcim/tables/sites.py:82 netbox/dcim/tables/sites.py:138 -#: netbox/ipam/forms/bulk_edit.py:255 netbox/ipam/forms/bulk_edit.py:305 -#: netbox/ipam/forms/bulk_edit.py:353 netbox/ipam/forms/bulk_edit.py:551 +#: netbox/ipam/forms/bulk_edit.py:256 netbox/ipam/forms/bulk_edit.py:306 +#: netbox/ipam/forms/bulk_edit.py:354 netbox/ipam/forms/bulk_edit.py:506 #: netbox/ipam/forms/bulk_import.py:192 netbox/ipam/forms/bulk_import.py:257 #: netbox/ipam/forms/bulk_import.py:293 netbox/ipam/forms/bulk_import.py:450 #: netbox/ipam/forms/filtersets.py:210 netbox/ipam/forms/filtersets.py:281 @@ -720,11 +719,11 @@ msgstr "" #: netbox/dcim/forms/filtersets.py:978 netbox/dcim/forms/filtersets.py:1008 #: netbox/dcim/forms/filtersets.py:1130 netbox/dcim/tables/power.py:88 #: netbox/extras/filtersets.py:612 netbox/extras/forms/filtersets.py:323 -#: netbox/extras/forms/filtersets.py:396 netbox/ipam/forms/bulk_edit.py:42 -#: netbox/ipam/forms/bulk_edit.py:67 netbox/ipam/forms/bulk_edit.py:111 -#: netbox/ipam/forms/bulk_edit.py:140 netbox/ipam/forms/bulk_edit.py:165 -#: netbox/ipam/forms/bulk_edit.py:250 netbox/ipam/forms/bulk_edit.py:300 -#: netbox/ipam/forms/bulk_edit.py:348 netbox/ipam/forms/bulk_edit.py:546 +#: netbox/extras/forms/filtersets.py:396 netbox/ipam/forms/bulk_edit.py:43 +#: netbox/ipam/forms/bulk_edit.py:68 netbox/ipam/forms/bulk_edit.py:112 +#: netbox/ipam/forms/bulk_edit.py:141 netbox/ipam/forms/bulk_edit.py:166 +#: netbox/ipam/forms/bulk_edit.py:251 netbox/ipam/forms/bulk_edit.py:301 +#: netbox/ipam/forms/bulk_edit.py:349 netbox/ipam/forms/bulk_edit.py:501 #: netbox/ipam/forms/bulk_import.py:38 netbox/ipam/forms/bulk_import.py:67 #: netbox/ipam/forms/bulk_import.py:95 netbox/ipam/forms/bulk_import.py:115 #: netbox/ipam/forms/bulk_import.py:135 netbox/ipam/forms/bulk_import.py:164 @@ -950,9 +949,9 @@ msgstr "" #: netbox/dcim/tables/devices.py:157 netbox/dcim/tables/power.py:30 #: netbox/dcim/tables/racks.py:118 netbox/dcim/tables/racks.py:212 #: netbox/extras/filtersets.py:536 netbox/extras/forms/filtersets.py:320 -#: netbox/ipam/forms/bulk_edit.py:460 netbox/ipam/forms/filtersets.py:173 -#: netbox/ipam/forms/filtersets.py:414 netbox/ipam/forms/filtersets.py:437 -#: netbox/ipam/forms/filtersets.py:467 netbox/templates/dcim/device.html:26 +#: netbox/ipam/forms/filtersets.py:173 netbox/ipam/forms/filtersets.py:414 +#: netbox/ipam/forms/filtersets.py:437 netbox/ipam/forms/filtersets.py:467 +#: netbox/templates/dcim/device.html:26 #: netbox/templates/dcim/device_edit.html:30 #: netbox/templates/dcim/inc/cable_termination.html:12 #: netbox/templates/dcim/location.html:26 @@ -992,11 +991,10 @@ msgstr "" #: netbox/dcim/forms/filtersets.py:1600 netbox/dcim/forms/filtersets.py:1624 #: netbox/dcim/forms/model_forms.py:112 netbox/dcim/forms/object_create.py:375 #: netbox/dcim/tables/devices.py:143 netbox/dcim/tables/sites.py:85 -#: netbox/extras/filtersets.py:503 netbox/ipam/forms/bulk_edit.py:207 -#: netbox/ipam/forms/bulk_edit.py:441 netbox/ipam/forms/bulk_edit.py:519 -#: netbox/ipam/forms/filtersets.py:217 netbox/ipam/forms/filtersets.py:422 -#: netbox/ipam/forms/filtersets.py:475 netbox/templates/dcim/device.html:18 -#: netbox/templates/dcim/rack.html:16 +#: netbox/extras/filtersets.py:503 netbox/ipam/forms/bulk_edit.py:208 +#: netbox/ipam/forms/bulk_edit.py:474 netbox/ipam/forms/filtersets.py:217 +#: netbox/ipam/forms/filtersets.py:422 netbox/ipam/forms/filtersets.py:475 +#: netbox/templates/dcim/device.html:18 netbox/templates/dcim/rack.html:16 #: netbox/templates/dcim/rackreservation.html:22 #: netbox/templates/dcim/region.html:26 netbox/templates/dcim/site.html:31 #: netbox/templates/ipam/prefix.html:49 netbox/templates/ipam/vlan.html:16 @@ -1016,9 +1014,9 @@ msgstr "" #: netbox/dcim/forms/filtersets.py:744 netbox/dcim/forms/filtersets.py:988 #: netbox/dcim/forms/filtersets.py:1102 netbox/dcim/forms/filtersets.py:1141 #: netbox/dcim/forms/object_create.py:383 netbox/extras/filtersets.py:520 -#: netbox/ipam/forms/bulk_edit.py:212 netbox/ipam/forms/bulk_edit.py:448 -#: netbox/ipam/forms/bulk_edit.py:524 netbox/ipam/forms/filtersets.py:222 -#: netbox/ipam/forms/filtersets.py:427 netbox/ipam/forms/filtersets.py:480 +#: netbox/ipam/forms/bulk_edit.py:213 netbox/ipam/forms/bulk_edit.py:479 +#: netbox/ipam/forms/filtersets.py:222 netbox/ipam/forms/filtersets.py:427 +#: netbox/ipam/forms/filtersets.py:480 #: netbox/virtualization/forms/bulk_edit.py:86 #: netbox/virtualization/forms/filtersets.py:69 #: netbox/virtualization/forms/filtersets.py:138 @@ -1083,7 +1081,7 @@ msgstr "" #: netbox/circuits/tables/circuits.py:155 netbox/dcim/forms/bulk_edit.py:117 #: netbox/dcim/forms/bulk_import.py:100 netbox/dcim/forms/model_forms.py:117 #: netbox/dcim/tables/sites.py:89 netbox/extras/forms/filtersets.py:480 -#: netbox/ipam/filtersets.py:999 netbox/ipam/forms/bulk_edit.py:538 +#: netbox/ipam/filtersets.py:999 netbox/ipam/forms/bulk_edit.py:493 #: netbox/ipam/forms/bulk_import.py:436 netbox/ipam/forms/model_forms.py:528 #: netbox/ipam/tables/fhrp.py:67 netbox/ipam/tables/vlans.py:122 #: netbox/ipam/tables/vlans.py:226 @@ -1168,7 +1166,7 @@ msgstr "" msgid "status" msgstr "" -#: netbox/circuits/models/circuits.py:84 netbox/templates/core/plugin.html:19 +#: netbox/circuits/models/circuits.py:84 netbox/templates/core/plugin.html:20 msgid "installed" msgstr "" @@ -1386,7 +1384,7 @@ msgstr "" #: netbox/extras/tables/tables.py:361 netbox/extras/tables/tables.py:378 #: netbox/extras/tables/tables.py:401 netbox/extras/tables/tables.py:439 #: netbox/extras/tables/tables.py:491 netbox/extras/tables/tables.py:514 -#: netbox/ipam/forms/bulk_edit.py:406 netbox/ipam/forms/filtersets.py:386 +#: netbox/ipam/forms/bulk_edit.py:407 netbox/ipam/forms/filtersets.py:386 #: netbox/ipam/tables/asn.py:16 netbox/ipam/tables/ip.py:85 #: netbox/ipam/tables/ip.py:160 netbox/ipam/tables/services.py:15 #: netbox/ipam/tables/services.py:40 netbox/ipam/tables/vlans.py:64 @@ -1396,7 +1394,7 @@ msgstr "" #: netbox/templates/circuits/provideraccount.html:28 #: netbox/templates/circuits/providernetwork.html:24 #: netbox/templates/core/datasource.html:34 netbox/templates/core/job.html:44 -#: netbox/templates/core/plugin.html:53 netbox/templates/core/rq_worker.html:43 +#: netbox/templates/core/plugin.html:54 netbox/templates/core/rq_worker.html:43 #: netbox/templates/dcim/consoleport.html:28 #: netbox/templates/dcim/consoleserverport.html:28 #: netbox/templates/dcim/devicebay.html:24 @@ -1654,7 +1652,7 @@ msgid "Cancelled" msgstr "" #: netbox/core/data_backends.py:32 netbox/core/tables/plugins.py:51 -#: netbox/templates/core/plugin.html:87 +#: netbox/templates/core/plugin.html:88 #: netbox/templates/dcim/interface.html:216 msgid "Local" msgstr "" @@ -2072,7 +2070,7 @@ msgstr "" #: netbox/core/models/data.py:49 netbox/extras/choices.py:37 #: netbox/extras/models/models.py:164 netbox/extras/tables/tables.py:656 #: netbox/templates/core/datasource.html:58 -#: netbox/templates/core/plugin.html:65 +#: netbox/templates/core/plugin.html:66 msgid "URL" msgstr "" @@ -2320,7 +2318,7 @@ msgstr "" msgid "No plugin data found" msgstr "" -#: netbox/core/tables/plugins.py:48 netbox/templates/core/plugin.html:61 +#: netbox/core/tables/plugins.py:48 netbox/templates/core/plugin.html:62 msgid "Author" msgstr "" @@ -2328,7 +2326,7 @@ msgstr "" msgid "Installed" msgstr "" -#: netbox/core/tables/plugins.py:57 netbox/templates/core/plugin.html:83 +#: netbox/core/tables/plugins.py:57 netbox/templates/core/plugin.html:84 msgid "Certified" msgstr "" @@ -3237,8 +3235,8 @@ msgstr "" #: netbox/dcim/tables/devices.py:626 netbox/ipam/filtersets.py:316 #: netbox/ipam/filtersets.py:327 netbox/ipam/filtersets.py:483 #: netbox/ipam/filtersets.py:584 netbox/ipam/filtersets.py:595 -#: netbox/ipam/forms/bulk_edit.py:241 netbox/ipam/forms/bulk_edit.py:297 -#: netbox/ipam/forms/bulk_edit.py:339 netbox/ipam/forms/bulk_import.py:157 +#: netbox/ipam/forms/bulk_edit.py:242 netbox/ipam/forms/bulk_edit.py:298 +#: netbox/ipam/forms/bulk_edit.py:340 netbox/ipam/forms/bulk_import.py:157 #: netbox/ipam/forms/bulk_import.py:243 netbox/ipam/forms/bulk_import.py:279 #: netbox/ipam/forms/filtersets.py:67 netbox/ipam/forms/filtersets.py:172 #: netbox/ipam/forms/filtersets.py:309 netbox/ipam/forms/model_forms.py:62 @@ -3501,7 +3499,7 @@ msgstr "" #: netbox/extras/forms/bulk_edit.py:53 netbox/extras/forms/bulk_edit.py:133 #: netbox/extras/forms/bulk_edit.py:183 netbox/extras/forms/bulk_edit.py:288 #: netbox/extras/forms/filtersets.py:64 netbox/extras/forms/filtersets.py:156 -#: netbox/extras/forms/filtersets.py:243 netbox/ipam/forms/bulk_edit.py:189 +#: netbox/extras/forms/filtersets.py:243 netbox/ipam/forms/bulk_edit.py:190 #: netbox/templates/dcim/device.html:324 #: netbox/templates/dcim/devicetype.html:49 #: netbox/templates/dcim/moduletype.html:34 netbox/templates/dcim/rack.html:81 @@ -3559,8 +3557,8 @@ msgstr "" #: netbox/dcim/tables/devices.py:169 netbox/dcim/tables/devices.py:809 #: netbox/dcim/tables/devices.py:937 netbox/dcim/tables/devicetypes.py:304 #: netbox/dcim/tables/racks.py:129 netbox/extras/filtersets.py:552 -#: netbox/ipam/forms/bulk_edit.py:260 netbox/ipam/forms/bulk_edit.py:310 -#: netbox/ipam/forms/bulk_edit.py:358 netbox/ipam/forms/bulk_edit.py:556 +#: netbox/ipam/forms/bulk_edit.py:261 netbox/ipam/forms/bulk_edit.py:311 +#: netbox/ipam/forms/bulk_edit.py:359 netbox/ipam/forms/bulk_edit.py:511 #: netbox/ipam/forms/bulk_import.py:197 netbox/ipam/forms/bulk_import.py:262 #: netbox/ipam/forms/bulk_import.py:298 netbox/ipam/forms/bulk_import.py:455 #: netbox/ipam/forms/filtersets.py:237 netbox/ipam/forms/filtersets.py:289 @@ -3630,8 +3628,8 @@ msgstr "" #: netbox/dcim/forms/model_forms.py:306 netbox/dcim/forms/model_forms.py:479 #: netbox/dcim/forms/model_forms.py:755 netbox/dcim/forms/object_create.py:400 #: netbox/dcim/tables/devices.py:161 netbox/dcim/tables/power.py:70 -#: netbox/dcim/tables/racks.py:217 netbox/ipam/forms/bulk_edit.py:468 -#: netbox/ipam/forms/filtersets.py:442 netbox/templates/dcim/device.html:30 +#: netbox/dcim/tables/racks.py:217 netbox/ipam/forms/filtersets.py:442 +#: netbox/templates/dcim/device.html:30 #: netbox/templates/dcim/inc/cable_termination.html:16 #: netbox/templates/dcim/powerfeed.html:28 netbox/templates/dcim/rack.html:13 #: netbox/templates/dcim/rack/base.html:4 @@ -4012,8 +4010,8 @@ msgid "Wireless LANs" msgstr "" #: netbox/dcim/forms/bulk_edit.py:1508 netbox/dcim/forms/filtersets.py:1328 -#: netbox/dcim/forms/model_forms.py:1390 netbox/ipam/forms/bulk_edit.py:285 -#: netbox/ipam/forms/bulk_edit.py:377 netbox/ipam/forms/filtersets.py:169 +#: netbox/dcim/forms/model_forms.py:1390 netbox/ipam/forms/bulk_edit.py:286 +#: netbox/ipam/forms/bulk_edit.py:378 netbox/ipam/forms/filtersets.py:169 #: netbox/templates/dcim/interface.html:122 #: netbox/templates/ipam/prefix.html:95 #: netbox/virtualization/forms/model_forms.py:349 @@ -4196,9 +4194,8 @@ msgstr "" #: netbox/dcim/forms/bulk_import.py:517 netbox/dcim/forms/filtersets.py:728 #: netbox/dcim/forms/filtersets.py:898 netbox/dcim/forms/model_forms.py:522 #: netbox/dcim/tables/devices.py:202 netbox/extras/filtersets.py:596 -#: netbox/extras/forms/filtersets.py:322 netbox/ipam/forms/bulk_edit.py:482 -#: netbox/ipam/forms/filtersets.py:415 netbox/ipam/forms/filtersets.py:447 -#: netbox/templates/dcim/device.html:239 +#: netbox/extras/forms/filtersets.py:322 netbox/ipam/forms/filtersets.py:415 +#: netbox/ipam/forms/filtersets.py:447 netbox/templates/dcim/device.html:239 #: netbox/templates/virtualization/cluster.html:10 #: netbox/templates/virtualization/virtualmachine.html:92 #: netbox/templates/virtualization/virtualmachine.html:101 @@ -4644,7 +4641,7 @@ msgid "Has virtual device contexts" msgstr "" #: netbox/dcim/forms/filtersets.py:903 netbox/extras/filtersets.py:585 -#: netbox/ipam/forms/bulk_edit.py:479 netbox/ipam/forms/filtersets.py:452 +#: netbox/ipam/forms/filtersets.py:452 #: netbox/virtualization/forms/filtersets.py:112 msgid "Cluster group" msgstr "" @@ -6847,7 +6844,7 @@ msgstr "" #: netbox/dcim/tables/sites.py:30 netbox/dcim/tables/sites.py:57 #: netbox/extras/forms/filtersets.py:351 netbox/extras/forms/model_forms.py:517 -#: netbox/ipam/forms/bulk_edit.py:130 netbox/ipam/forms/model_forms.py:153 +#: netbox/ipam/forms/bulk_edit.py:131 netbox/ipam/forms/model_forms.py:153 #: netbox/ipam/tables/asn.py:66 netbox/netbox/navigation/menu.py:15 #: netbox/netbox/navigation/menu.py:17 msgid "Sites" @@ -9009,7 +9006,7 @@ msgid "Prefixes which contain this prefix or IP" msgstr "" #: netbox/ipam/filtersets.py:304 netbox/ipam/filtersets.py:572 -#: netbox/ipam/forms/bulk_edit.py:342 netbox/ipam/forms/filtersets.py:196 +#: netbox/ipam/forms/bulk_edit.py:343 netbox/ipam/forms/filtersets.py:196 #: netbox/ipam/forms/filtersets.py:331 msgid "Mask length" msgstr "" @@ -9135,16 +9132,16 @@ msgstr "" msgid "Address pattern" msgstr "" -#: netbox/ipam/forms/bulk_edit.py:49 +#: netbox/ipam/forms/bulk_edit.py:50 msgid "Enforce unique space" msgstr "" -#: netbox/ipam/forms/bulk_edit.py:87 +#: netbox/ipam/forms/bulk_edit.py:88 msgid "Is private" msgstr "" -#: netbox/ipam/forms/bulk_edit.py:108 netbox/ipam/forms/bulk_edit.py:137 -#: netbox/ipam/forms/bulk_edit.py:162 netbox/ipam/forms/bulk_import.py:89 +#: netbox/ipam/forms/bulk_edit.py:109 netbox/ipam/forms/bulk_edit.py:138 +#: netbox/ipam/forms/bulk_edit.py:163 netbox/ipam/forms/bulk_import.py:89 #: netbox/ipam/forms/bulk_import.py:109 netbox/ipam/forms/bulk_import.py:129 #: netbox/ipam/forms/filtersets.py:110 netbox/ipam/forms/filtersets.py:125 #: netbox/ipam/forms/filtersets.py:148 netbox/ipam/forms/model_forms.py:96 @@ -9158,18 +9155,18 @@ msgstr "" msgid "RIR" msgstr "" -#: netbox/ipam/forms/bulk_edit.py:170 +#: netbox/ipam/forms/bulk_edit.py:171 msgid "Date added" msgstr "" -#: netbox/ipam/forms/bulk_edit.py:228 netbox/ipam/forms/model_forms.py:586 +#: netbox/ipam/forms/bulk_edit.py:229 netbox/ipam/forms/model_forms.py:586 #: netbox/ipam/forms/model_forms.py:633 netbox/ipam/tables/ip.py:251 #: netbox/templates/ipam/vlan_edit.html:37 #: netbox/templates/ipam/vlangroup.html:27 msgid "VLAN Group" msgstr "" -#: netbox/ipam/forms/bulk_edit.py:233 netbox/ipam/forms/bulk_import.py:185 +#: netbox/ipam/forms/bulk_edit.py:234 netbox/ipam/forms/bulk_import.py:185 #: netbox/ipam/forms/filtersets.py:256 netbox/ipam/forms/model_forms.py:218 #: netbox/ipam/models/vlans.py:234 netbox/ipam/tables/ip.py:255 #: netbox/templates/ipam/prefix.html:60 netbox/templates/ipam/vlan.html:12 @@ -9184,30 +9181,30 @@ msgstr "" msgid "VLAN" msgstr "" -#: netbox/ipam/forms/bulk_edit.py:244 +#: netbox/ipam/forms/bulk_edit.py:245 msgid "Prefix length" msgstr "" -#: netbox/ipam/forms/bulk_edit.py:267 netbox/ipam/forms/filtersets.py:241 +#: netbox/ipam/forms/bulk_edit.py:268 netbox/ipam/forms/filtersets.py:241 #: netbox/templates/ipam/prefix.html:85 msgid "Is a pool" msgstr "" -#: netbox/ipam/forms/bulk_edit.py:272 netbox/ipam/forms/bulk_edit.py:317 +#: netbox/ipam/forms/bulk_edit.py:273 netbox/ipam/forms/bulk_edit.py:318 #: netbox/ipam/forms/filtersets.py:248 netbox/ipam/forms/filtersets.py:293 #: netbox/ipam/models/ip.py:272 netbox/ipam/models/ip.py:539 msgid "Treat as fully utilized" msgstr "" -#: netbox/ipam/forms/bulk_edit.py:286 netbox/ipam/forms/filtersets.py:171 +#: netbox/ipam/forms/bulk_edit.py:287 netbox/ipam/forms/filtersets.py:171 msgid "VLAN Assignment" msgstr "" -#: netbox/ipam/forms/bulk_edit.py:365 netbox/ipam/models/ip.py:772 +#: netbox/ipam/forms/bulk_edit.py:366 netbox/ipam/models/ip.py:772 msgid "DNS name" msgstr "" -#: netbox/ipam/forms/bulk_edit.py:386 netbox/ipam/forms/bulk_edit.py:579 +#: netbox/ipam/forms/bulk_edit.py:387 netbox/ipam/forms/bulk_edit.py:534 #: netbox/ipam/forms/bulk_import.py:394 netbox/ipam/forms/bulk_import.py:469 #: netbox/ipam/forms/bulk_import.py:495 netbox/ipam/forms/filtersets.py:390 #: netbox/ipam/forms/filtersets.py:530 netbox/templates/ipam/fhrpgroup.html:22 @@ -9217,12 +9214,12 @@ msgstr "" msgid "Protocol" msgstr "" -#: netbox/ipam/forms/bulk_edit.py:393 netbox/ipam/forms/filtersets.py:397 +#: netbox/ipam/forms/bulk_edit.py:394 netbox/ipam/forms/filtersets.py:397 #: netbox/ipam/tables/fhrp.py:22 netbox/templates/ipam/fhrpgroup.html:26 msgid "Group ID" msgstr "" -#: netbox/ipam/forms/bulk_edit.py:398 netbox/ipam/forms/filtersets.py:402 +#: netbox/ipam/forms/bulk_edit.py:399 netbox/ipam/forms/filtersets.py:402 #: netbox/wireless/forms/bulk_edit.py:68 netbox/wireless/forms/bulk_edit.py:115 #: netbox/wireless/forms/bulk_import.py:62 #: netbox/wireless/forms/bulk_import.py:65 @@ -9233,11 +9230,11 @@ msgstr "" msgid "Authentication type" msgstr "" -#: netbox/ipam/forms/bulk_edit.py:403 netbox/ipam/forms/filtersets.py:406 +#: netbox/ipam/forms/bulk_edit.py:404 netbox/ipam/forms/filtersets.py:406 msgid "Authentication key" msgstr "" -#: netbox/ipam/forms/bulk_edit.py:420 netbox/ipam/forms/filtersets.py:383 +#: netbox/ipam/forms/bulk_edit.py:421 netbox/ipam/forms/filtersets.py:383 #: netbox/ipam/forms/model_forms.py:474 netbox/netbox/navigation/menu.py:386 #: netbox/templates/ipam/fhrpgroup.html:49 #: netbox/templates/wireless/inc/authentication_attrs.html:5 @@ -9249,25 +9246,25 @@ msgstr "" msgid "Authentication" msgstr "" -#: netbox/ipam/forms/bulk_edit.py:432 netbox/ipam/forms/model_forms.py:575 +#: netbox/ipam/forms/bulk_edit.py:436 netbox/ipam/forms/model_forms.py:575 msgid "Scope type" msgstr "" -#: netbox/ipam/forms/bulk_edit.py:490 netbox/ipam/models/vlans.py:60 -msgid "VLAN ID ranges" -msgstr "" - -#: netbox/ipam/forms/bulk_edit.py:498 netbox/ipam/forms/model_forms.py:578 -#: netbox/ipam/forms/model_forms.py:588 netbox/ipam/tables/vlans.py:71 -#: netbox/templates/ipam/vlangroup.html:38 +#: netbox/ipam/forms/bulk_edit.py:439 netbox/ipam/forms/bulk_edit.py:453 +#: netbox/ipam/forms/model_forms.py:578 netbox/ipam/forms/model_forms.py:588 +#: netbox/ipam/tables/vlans.py:71 netbox/templates/ipam/vlangroup.html:38 msgid "Scope" msgstr "" -#: netbox/ipam/forms/bulk_edit.py:570 +#: netbox/ipam/forms/bulk_edit.py:446 netbox/ipam/models/vlans.py:60 +msgid "VLAN ID ranges" +msgstr "" + +#: netbox/ipam/forms/bulk_edit.py:525 msgid "Site & Group" msgstr "" -#: netbox/ipam/forms/bulk_edit.py:584 netbox/ipam/forms/model_forms.py:659 +#: netbox/ipam/forms/bulk_edit.py:539 netbox/ipam/forms/model_forms.py:659 #: netbox/ipam/forms/model_forms.py:691 netbox/ipam/tables/services.py:19 #: netbox/ipam/tables/services.py:49 netbox/templates/ipam/service.html:36 #: netbox/templates/ipam/servicetemplate.html:23 @@ -10849,7 +10846,7 @@ msgstr "" #: netbox/netbox/navigation/menu.py:454 netbox/netbox/navigation/menu.py:502 #: netbox/templates/500.html:35 netbox/templates/account/preferences.html:22 -#: netbox/templates/core/plugin.html:12 +#: netbox/templates/core/plugin.html:13 #: netbox/templates/core/plugin_list.html:7 #: netbox/templates/core/plugin_list.html:12 msgid "Plugins" @@ -11088,19 +11085,19 @@ msgstr "" msgid "Row {i}: Object with ID {id} does not exist" msgstr "" -#: netbox/netbox/views/generic/bulk_views.py:699 -#: netbox/netbox/views/generic/bulk_views.py:897 -#: netbox/netbox/views/generic/bulk_views.py:945 +#: netbox/netbox/views/generic/bulk_views.py:702 +#: netbox/netbox/views/generic/bulk_views.py:900 +#: netbox/netbox/views/generic/bulk_views.py:948 #, python-brace-format msgid "No {object_type} were selected." msgstr "" -#: netbox/netbox/views/generic/bulk_views.py:779 +#: netbox/netbox/views/generic/bulk_views.py:782 #, python-brace-format msgid "Renamed {count} {object_type}" msgstr "" -#: netbox/netbox/views/generic/bulk_views.py:875 +#: netbox/netbox/views/generic/bulk_views.py:878 #, python-brace-format msgid "Deleted {count} {object_type}" msgstr "" @@ -11769,35 +11766,35 @@ msgstr "" msgid "Indefinite" msgstr "" -#: netbox/templates/core/plugin.html:21 +#: netbox/templates/core/plugin.html:22 msgid "Not installed" msgstr "" -#: netbox/templates/core/plugin.html:32 +#: netbox/templates/core/plugin.html:33 msgid "Overview" msgstr "" -#: netbox/templates/core/plugin.html:38 +#: netbox/templates/core/plugin.html:39 msgid "Install" msgstr "" -#: netbox/templates/core/plugin.html:50 +#: netbox/templates/core/plugin.html:51 msgid "Plugin Details" msgstr "" -#: netbox/templates/core/plugin.html:57 +#: netbox/templates/core/plugin.html:58 msgid "Summary" msgstr "" -#: netbox/templates/core/plugin.html:75 +#: netbox/templates/core/plugin.html:76 msgid "License" msgstr "" -#: netbox/templates/core/plugin.html:95 +#: netbox/templates/core/plugin.html:96 msgid "Version History" msgstr "" -#: netbox/templates/core/plugin.html:106 +#: netbox/templates/core/plugin.html:107 msgid "Local Installation Instructions" msgstr "" diff --git a/netbox/utilities/forms/widgets/select.py b/netbox/utilities/forms/widgets/select.py index 9108951b7..8115e2449 100644 --- a/netbox/utilities/forms/widgets/select.py +++ b/netbox/utilities/forms/widgets/select.py @@ -43,9 +43,12 @@ class HTMXSelect(forms.Select): """ Selection widget that will re-generate the HTML form upon the selection of a new option. """ - def __init__(self, hx_url='.', hx_target_id='form_fields', attrs=None, **kwargs): + def __init__(self, method='get', hx_url='.', hx_target_id='form_fields', attrs=None, **kwargs): + method = method.lower() + if method not in ('delete', 'get', 'patch', 'post', 'put'): + raise ValueError(f"Unsupported HTTP method: {method}") _attrs = { - 'hx-get': hx_url, + f'hx-{method}': hx_url, 'hx-include': f'#{hx_target_id}', 'hx-target': f'#{hx_target_id}', } diff --git a/netbox/wireless/graphql/types.py b/netbox/wireless/graphql/types.py index e542fd9c9..b24525fbe 100644 --- a/netbox/wireless/graphql/types.py +++ b/netbox/wireless/graphql/types.py @@ -23,6 +23,7 @@ class WirelessLANGroupType(OrganizationalObjectType): parent: Annotated["WirelessLANGroupType", strawberry.lazy('wireless.graphql.types')] | None wireless_lans: List[Annotated["WirelessLANType", strawberry.lazy('wireless.graphql.types')]] + children: List[Annotated["WirelessLANGroupType", strawberry.lazy('wireless.graphql.types')]] @strawberry_django.type(