Compare commits

..

99 Commits

Author SHA1 Message Date
bctiemann
c4304d059c Merge pull request #18703 from netbox-community/release-v4.2.4
Release v4.2.4
2025-02-21 15:34:15 -05:00
Brian Tiemann
fee66438f3 Fix django-htmx version 2025-02-21 15:19:54 -05:00
Brian Tiemann
0f52712468 Release v4.2.4 2025-02-21 15:15:14 -05:00
Jeremy Stretch
fbaa82df7b Fixes #18674: Fix form reset when selecting a value from a speed selection dropdown 2025-02-21 14:04:50 -05:00
mr1716
9c1358e6e7 #18698 Correct REST Wikipedia URL In Documentation 2025-02-21 09:34:16 -05:00
github-actions
63b7145baa Update source translation strings 2025-02-21 05:02:07 +00:00
Jeremy Stretch
bcd974210d Update Transifex resource slug 2025-02-20 12:53:25 -05:00
Jason Novinger
ed79e3bbf4 Fixes #18619: shift-select selects hidden items
This also fixes the inverse, when a range is unselected via shift-click,
previously checked checkboxes that are hidden are not changed.
2025-02-20 10:17:43 -05:00
Alexander Haase
b5bc0bad38 Cover multitable inheritance in serialization
During serialization, custom fields may be available to a model due to
multi-table inheritance, but might not be available in serialized data
because only direct fields of the model are covered. Now this attribute
is only used if available in serialized data. Models using multi-table
inheritance must modify their serialize_object() method to cover parent
serialization.
2025-02-20 10:09:35 -05:00
Jason Novinger
2a44affd03 Fixes #18594: asn_count sort in Sites list (#18634)
* Fixes #18594: asn_count sort in Sites list

* Fixes similar issue in `circuits.views.ProviderListView`

Thanks @bctiemann for point this out!
2025-02-20 10:01:04 -05:00
github-actions
57ef44706a Update source translation strings 2025-02-19 05:02:03 +00:00
Jason Novinger
70dddb673b Fixes #18585: filtering circuits by location (#18641)
* Fixes #18585: filtering circuits by location

This also fixes a related issue where selected filter is not shown in
the filter form.

Changes:
- Adds `CircuitFilterSet.location_id` field to enable filtering with
  incoming GET params
- Adds `CirciotFilterForm.location_id` field to enable filtering from
  list form
- Adds `location_id` to the Location fieldset on `CircuitFilterForm`

* Adds test for new CircuitFilterset.location_id filter
2025-02-18 13:33:05 -05:00
Alexander Haase
6c6cb321bf Fixes 18555: Fix model URL generator for plugins (#18607)
* Fix model URL generator for plugins

* Fix reverse accessor warning

* Revert "Fix reverse accessor warning"

This reverts commit f07642bb99.

* Add URL test case for regular models

* Split dummy models

Instead of using a single model for testing, one is used for testing the
plugin API and a dedicated one is used for testing the NetBox plugin
model features.

* Fix filterset test case error

* Rename test module

---------

Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
2025-02-18 09:11:32 -05:00
Renato Almeida de Oliveira
11514bfb21 Fixes: #18584 Add rack types column to manufacturers table (#18636)
* Add racktype_count annotation to list view queryset, create the LinkedCountColumn in ManufacturerTable

* Add Manufacturer field to RackTypeFilterForm
2025-02-18 08:41:12 -05:00
github-actions
c324d23634 Update source translation strings 2025-02-15 05:02:03 +00:00
Alexander Haase
f9431f1c29 Replace DurationChoices by JobIntervalChoices 2025-02-14 14:42:27 -05:00
Renato Almeida de Oliveira Zaroubin
b1ac20ac19 Update ModuleBay instance name before saving it 2025-02-14 14:22:29 -05:00
github-actions
f8022040b2 Update source translation strings 2025-02-12 05:02:12 +00:00
Tobias Genannt
8114492673 Close #18357: Display author name for plugins 2025-02-11 12:19:43 -05:00
Renato Almeida de Oliveira
154b3a7abb Fixes: 18593 - "Create & Add Another" broken for new IP addresses (#18602)
* update IPAddressEditView get_extra_addanother_params

* Simplify get_extra_addanother_params
2025-02-11 08:31:40 -05:00
github-actions
015ef25ca0 Update source translation strings 2025-02-10 18:34:35 +00:00
Alexander Haase
3e1cc0d7f3 Fixes 18208: Consolidate rendering configuration templates (#18604) 2025-02-10 11:03:08 -05:00
Alexander Haase
e1d1aab4bd Omit empty related models 2025-02-10 10:56:09 -05:00
Matej Vadnjal
299bde9653 use script form's cleaned data when calling script from CLI
so ObjectVar and other field values have proper types in script's data variable
2025-02-10 09:46:59 -05:00
Alexander Haase
4b98f74943 Fixes 18247: Fix dark mode button classes (#18617) 2025-02-10 09:42:08 -05:00
Jeremy Stretch
a33fb2a0a9 Closes #17918: Fix styling of "tagged items" list under tag view 2025-02-10 09:00:55 -05:00
github-actions
13dc6854c2 Update source translation strings 2025-02-08 05:02:19 +00:00
Antoine Keranflec'h
e475386936 Fixes: #18408 add STATUS_PAUSED to VirtualMachine (#18595)
* feat(vm): add extra status

* keep only usefull status

---------

Co-authored-by: Antoine Keranflec'h <antoine.keranflech@worldline.com>
2025-02-07 16:41:45 -05:00
Jeremy Stretch
0b194e363e Docs cleanup 2025-02-07 15:33:37 -05:00
github-actions
72e93b04da Update source translation strings 2025-02-07 05:02:00 +00:00
Renato Almeida de Oliveira
7794b6718a Fixes: #18013 - All saved filters showing up for Change Log table, regardless of defined object type (#18551)
* Setup ObjectChangeFilterForm __init__ to add query_param to filter_id

* code lint, move __init__ to end of class

* Move filter_id widget setup to SavedFiltersMixin, and add model attributes to Models FilterForms

* Add missing model declarations for filter forms

---------

Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
2025-02-06 17:21:46 -05:00
Renato Almeida de Oliveira
efa939d0c2 Fixes: #18241 - Script results log_threshold should default to Default (#18501)
* Changed LogLevelChoices order; Changed ScriptResultView to select LogLevelChoices to LOG_DEFAULT and setup the html template to put (All) in the last one

* Change LogLevelChoices in ScriptResultView get_table method

* Remove default option, add Default string to INFO

* Fix scripts.py and reports.py to reflect removing DEFAULT level

* fix linting
2025-02-06 16:30:25 -05:00
Jeremy Stretch
8e91db0394 Misc cleanup of the release checklist 2025-02-05 11:40:53 -05:00
bctiemann
260adfc9e7 Merge pull request #18569 from netbox-community/release-v4.2.3
Release 4.2.3
2025-02-04 15:35:45 -05:00
Brian Tiemann
9391f48d62 Update static bundle 2025-02-04 15:20:08 -05:00
Brian Tiemann
6e165435e2 Release 4.2.3 2025-02-04 15:09:37 -05:00
mr1716
29f405d27e #18496 Fixing Broken Link For Custom Links Documentation 2025-02-03 10:12:29 -05:00
Jeremy Stretch
f829f34b43 Closes #18559: Add a build parameter to ReleaseInfo (#18560)
* Closes #18559: Add a build parameter to ReleaseInfo

* Adjust dataclass typing
2025-02-03 09:44:00 -05:00
github-actions
0b794de40e Update source translation strings 2025-02-01 05:02:11 +00:00
Brian Tiemann
b2bc842f1c Remove 'provider' from VirtualCircuitIndex.display_attrs 2025-01-31 14:42:39 -05:00
Brian Tiemann
c8decf4c21 Add auth_required attrib on PluginMenuItem 2025-01-31 14:40:49 -05:00
Renato Almeida de Oliveira Zaroubin
e12a5d2edc Add get_extra_addanother_params method in IPAddressEditView 2025-01-31 14:33:26 -05:00
bctiemann
4c5fbb7326 Merge pull request #18544 from renatoalmeidaoliveira/18154-make-BaseTable-aware-default_user_preferences-annon-users
FIX #18154 - Cannot change default table preferences for anonymous users
2025-01-31 14:25:20 -05:00
mr1716
8aecf53d0e #18513 Updating Documentation Relating To Strawberry-Django Links 2025-01-31 14:14:48 -05:00
Renato Almeida de Oliveira Zaroubin
7d6089775e remove extra line 2025-01-31 18:48:50 +00:00
Renato Almeida de Oliveira Zaroubin
f5bdf7b593 Simplify Anon user logic 2025-01-31 18:03:55 +00:00
Renato Almeida de Oliveira Zaroubin
62148bb83c Check if DEFAULT_USER_PREFERENCES are configured 2025-01-30 21:51:37 +00:00
Renato Almeida de Oliveira Zaroubin
22af6dd05f Add default user preferences tables testing in BaseTable 2025-01-30 21:09:36 +00:00
github-actions
5514df9dee Update source translation strings 2025-01-30 05:02:02 +00:00
Brian Tiemann
5cd7c6d167 Add <meta> tag reflecting settings.HOSTNAME 2025-01-29 12:50:08 -05:00
bctiemann
9ac79ebbdf Merge pull request #18516 from tobiasge/dont-fail-on-debug
Fix #18515: Don't fail in DEBUG mode
2025-01-28 15:20:52 -05:00
bctiemann
e6c0519ada Merge pull request #18517 from mr1716/main
#18512 Update required-parameters spelling
2025-01-28 15:17:59 -05:00
Tobias Genannt
07403f690a Fix #18515: Don't fail in DEBUG mode
When no Redis server is reachable management commands failed without
this try...except block.
2025-01-28 19:40:22 +01:00
mr1716
80e466dab7 #18512 Update required-parameters spelling 2025-01-28 09:06:37 -05:00
Brian Tiemann
34fa3835be NB-717 Update dashboard news feed URL to eliminate multiple 301 redirects 2025-01-28 08:26:35 -05:00
Brian Tiemann
7a6bb34d21 Reword references to develop and master branches 2025-01-28 08:26:05 -05:00
github-actions
968214b64a Update source translation strings 2025-01-28 05:02:09 +00:00
bctiemann
cf64f3cc43 Merge pull request #18444 from netbox-community/18433-fix-macaddress-primary-for-interface
Fixes: #18433 - Fix missing is_primary property on MACAddress model
2025-01-27 13:50:28 -05:00
Daniel Sheppard
ee5d7cfe31 Merge branch 'main' into 18433-fix-macaddress-primary-for-interface 2025-01-27 12:11:37 -06:00
Jeremy Stretch
57fa1dd18d Add remaining issue types 2025-01-24 10:20:43 -05:00
Jeremy Stretch
b2b47ac740 Closes #18484: Exempt changes to GitHub templates from CI 2025-01-24 09:47:40 -05:00
Jeremy Stretch
313f44646b Assign GitHub issue type on creation 2025-01-24 09:33:04 -05:00
Brian Tiemann
c2daa70099 Fix typo in Site Groups docs 2025-01-24 08:10:39 -05:00
Brian Tiemann
5fce4eef8e Add note about \l command 2025-01-24 08:09:10 -05:00
Brian Tiemann
b1e7530295 Add warning about UTF8 encoding in PostgreSQL 2025-01-24 08:09:10 -05:00
github-actions
da9b452327 Update source translation strings 2025-01-24 05:02:20 +00:00
bctiemann
31efd1fe57 Merge pull request #18452 from netbox-community/18449-fix-formatting-errors
Fixes: #18449 - Clean up some formatting errors
2025-01-23 19:51:42 -05:00
bctiemann
a8168899b8 Merge pull request #18450 from netbox-community/18447-fix-legacy-macaddress-sorting
Fixes: #18447 - Fix sorting by `mac_address` field
2025-01-23 19:50:12 -05:00
bctiemann
e02ae72f0c Merge pull request #18445 from netbox-community/18436-fix-unassign-mac-with-primary
Fixes: #18436 - Prevent unassigning mac address when primary on an interface
2025-01-23 19:45:53 -05:00
Daniel Sheppard
3219609253 Change to @cached_property 2025-01-23 18:30:54 -06:00
Daniel Sheppard
adcb6bebd2 Remove mac_address from tables. 2025-01-22 14:14:56 -06:00
Daniel Sheppard
ad4e4e89a7 Update VirtualMachineVMInterfaceTable 2025-01-21 11:15:33 -06:00
Daniel Sheppard
c56a39a168 Fixes: #18449 - Clean up some formatting errors 2025-01-21 10:44:46 -06:00
Daniel Sheppard
d1914595f6 Fixes: #18447 - Fix sorting by mac_address field
* Disable sorting by `mac_address` for legacy `mac_address` field for Device and VM Interfaces
* Ensure `primary_mac_address` field is included in field list for Device and VM Interfaces
2025-01-21 10:15:33 -06:00
Jeremy Stretch
b913661297 Fixes #18438: Specify batch_size for migrations which run bulk_update() 2025-01-21 09:48:35 -05:00
Daniel Sheppard
bec97df242 Fix Tests 2025-01-20 23:44:36 -06:00
Daniel Sheppard
22e320084a Update UI to disable interface assignment when assigned as primary 2025-01-20 23:06:29 -06:00
Daniel Sheppard
277acd3a31 Fixes: #18436 - Prevent unassigning mac address when primary on an interface 2025-01-20 22:49:55 -06:00
Daniel Sheppard
51a79505fe Fixes: #18433 - Fix missing is_primary property on MACAddress model 2025-01-20 22:21:36 -06:00
github-actions
d11deb6678 Update source translation strings 2025-01-18 05:02:12 +00:00
Jeremy Stretch
f845b2cf07 Release v4.2.2 2025-01-17 15:05:09 -05:00
atownson
2ed4a2b005 Fixes: #18369 - Remove the json filter for protection rules (#18388)
* Remove the json filter for protection rules

* Configure PROTECTION_RULE config attribute to use ConfigJSONEncoder as serializer

* Tweak getattr()

---------

Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
2025-01-17 14:02:12 -05:00
Jeremy Stretch
5b9210dfa5 Fixes #18392: Exclude config contexts assigned to locations for VMs 2025-01-17 13:14:05 -05:00
Jeremy Stretch
4a13664e0f Closes #18425: Remove the triage priority field from GitHub issue templates 2025-01-17 11:06:17 -05:00
Jeremy Stretch
a9f3c74b0c Fixes #18379: Ensure RSS feed content within dashboard widget is sanitized 2025-01-17 10:25:22 -05:00
Brian Tiemann
50b7f46fc0 Migrate DEFAULT_FILE_STORAGE to STORAGES 2025-01-17 09:04:51 -05:00
Brian Tiemann
07ad4c1321 Make GFK scope field sortable=False on tables where it appears 2025-01-17 08:52:12 -05:00
bctiemann
4a1fea3504 Fixes: #18336 - Perform Rack object validation of u_height and starting_unit on rack_type if present (#18395)
* Perform Rack object validation of u_height and starting_unit on rack_type if present

* Calculate effective values before doing validation
2025-01-17 08:45:17 -05:00
bctiemann
993d8f1480 Fixes: #18373 - Fix validation of site in Assign Device to Cluster flow (#18375)
* Fix validation of site in Assign Device to Cluster flow

* Validate Location as well as Site scope
2025-01-17 08:35:17 -05:00
bctiemann
c3efa2149c Fixes: #18350 - Remove 'site' and 'provider_network' from CircuitTerminationIndex.display_attrs (#18351)
* Remove 'site' and 'provider_network' from CircuitTerminationIndex.display_attrs

* Use '_site' and '_provider_network' in display_attrs

* Replace private fields with 'termination'
2025-01-17 08:28:43 -05:00
Jeremy Stretch
a75fa53d4d Closes #18348: Disable legacy pre-commit hook script 2025-01-13 08:50:34 -05:00
Jeremy Stretch
e75d327f38 Fixes #18376: Include tagged VLANs in interfaces list for Q-in-Q interfaces 2025-01-10 09:10:34 -05:00
github-actions
a79d869bd8 Update source translation strings 2025-01-10 05:02:08 +00:00
Brian Tiemann
32422d1683 Don't cache CACHE_KEY_CATALOG_ERROR if ISOLATED_DEPLOYMENT is True 2025-01-09 15:21:27 -05:00
Jeremy Stretch
571f604ce8 Fixes #18368: Restore missing fields on REST API serializer for MAC addresses 2025-01-09 14:53:03 -05:00
Jeremy Stretch
b12c8c880f Fixes #18363: Fix assignment of MAC addresses to interfaces via REST API (#18367)
* Fixes #18363: Fix assignment of MAC addresses to interfaces via REST API

* Add missing API & view tests
2025-01-09 13:55:19 -05:00
Jeremy Stretch
b11f179527 Closes #18362: Create a system job for census reporting 2025-01-09 11:56:09 -05:00
Brian Tiemann
80e1fd02bb Update docs to indicate PostgreSQL 13+ requirement 2025-01-09 10:58:51 -05:00
github-actions
4090afbf24 Update source translation strings 2025-01-09 05:02:09 +00:00
135 changed files with 2800 additions and 2431 deletions

View File

@@ -1,5 +1,6 @@
---
name: ✨ Feature Request
type: Feature
description: Propose a new NetBox feature or enhancement
labels: ["type: feature", "status: needs triage"]
body:
@@ -14,7 +15,7 @@ body:
attributes:
label: NetBox version
description: What version of NetBox are you currently running?
placeholder: v4.2.1
placeholder: v4.2.4
validations:
required: true
- type: dropdown
@@ -27,19 +28,6 @@ body:
- Other
validations:
required: true
- type: dropdown
attributes:
label: Triage priority
description: >
Issue triage may be prioritized in some cases. Select whichever of the following
conditions applies, if any.
options:
- I volunteer to perform this work (if approved)
- I'm a NetBox Labs customer
- N/A
default: 2
validations:
required: true
- type: textarea
attributes:
label: Proposed functionality

View File

@@ -1,5 +1,6 @@
---
name: 🐛 Bug Report
type: Bug
description: Report a reproducible bug in the current release of NetBox
labels: ["type: bug", "status: needs triage"]
body:
@@ -22,24 +23,11 @@ body:
- Self-hosted
validations:
required: true
- type: dropdown
attributes:
label: Triage priority
description: >
Issue triage may be prioritized in some cases. Select whichever of the following
conditions applies, if any.
options:
- I volunteer to perform this work (if approved)
- I'm a NetBox Labs customer
- N/A
default: 2
validations:
required: true
- type: input
attributes:
label: NetBox Version
description: What version of NetBox are you currently running?
placeholder: v4.2.1
placeholder: v4.2.4
validations:
required: true
- type: dropdown

View File

@@ -1,5 +1,6 @@
---
name: 📖 Documentation Change
type: Documentation
description: Suggest an addition or modification to the NetBox documentation
labels: ["type: documentation", "status: needs triage"]
body:

View File

@@ -1,5 +1,6 @@
---
name: 🌍 Translation
type: Translation
description: Request support for a new language in the user interface
labels: ["type: translation"]
body:

View File

@@ -1,5 +1,6 @@
---
name: 🏡 Housekeeping
type: Housekeeping
description: A change pertaining to the codebase itself (developers only)
labels: ["type: housekeeping"]
body:

View File

@@ -1,5 +1,6 @@
---
name: 🗑️ Deprecation
type: Deprecation
description: The removal of an existing feature or resource
labels: ["type: deprecation"]
body:

View File

@@ -3,11 +3,15 @@ name: CI
on:
push:
paths-ignore:
- '.github/ISSUE_TEMPLATE/**'
- '.github/PULL_REQUEST_TEMPLATE.md'
- 'contrib/**'
- 'docs/**'
- 'netbox/translations/**'
pull_request:
paths-ignore:
- '.github/ISSUE_TEMPLATE/**'
- '.github/PULL_REQUEST_TEMPLATE.md'
- 'contrib/**'
- 'docs/**'
- 'netbox/translations/**'

View File

@@ -1,7 +1,7 @@
[main]
host = https://app.transifex.com
[o:netbox-community:p:netbox:r:9cbf4fcf95b3d92e4ebbf1a5e5d1caee]
[o:netbox-community:p:netbox:r:034999968a7366ba27a8bdf1ab63bf42]
file_filter = netbox/translations/<lang>/LC_MESSAGES/django.po
source_file = netbox/translations/en/LC_MESSAGES/django.po
type = PO

View File

@@ -84,7 +84,7 @@ intake policy](https://github.com/netbox-community/netbox/wiki/Issue-Intake-Poli
* It's very important that you not submit a pull request until a relevant issue has been opened **and** assigned to you. Otherwise, you risk wasting time on work that may ultimately not be needed.
* New pull requests should generally be based off of the `develop` branch, rather than `master`. The `develop` branch is used for ongoing development, while `master` is used for tracking stable releases. (If you're developing for an upcoming minor release, use `feature` instead.)
* New pull requests should generally be based off of the `main` branch. This branch, in keeping with the [trunk-based development](https://trunkbaseddevelopment.com/) approach, is used for ongoing development and bug fixes and always represents the newest stable code, from which releases are periodically branched. (If you're developing for an upcoming minor release, use `feature` instead.)
* In most cases, it is not necessary to add a changelog entry: A maintainer will take care of this when the PR is merged. (This helps avoid merge conflicts resulting from multiple PRs being submitted simultaneously.)

View File

@@ -8,8 +8,6 @@ django-cors-headers
# Runtime UI tool for debugging Django
# https://github.com/jazzband/django-debug-toolbar/blob/main/docs/changes.rst
# Pinned for DNS looukp bug; see https://github.com/netbox-community/netbox/issues/16454
# and https://github.com/jazzband/django-debug-toolbar/issues/1927
django-debug-toolbar
# Library for writing reusable URL query filters
@@ -90,7 +88,8 @@ mkdocs-material
# Introspection for embedded code
# https://github.com/mkdocstrings/mkdocstrings/blob/main/CHANGELOG.md
mkdocstrings[python-legacy]
# See #18568
mkdocstrings[python-legacy]==0.27.0
# Library for manipulating IP prefixes and addresses
# https://github.com/netaddr/netaddr/blob/master/CHANGELOG.rst

View File

@@ -2,7 +2,7 @@
## ALLOWED_HOSTS
This is a list of valid fully-qualified domain names (FQDNs) and/or IP addresses that can be used to reach the NetBox service. Usually this is the same as the hostname for the NetBox server, but can also be different; for example, when using a reverse proxy serving the NetBox website under a different FQDN than the hostname of the NetBox server. To help guard against [HTTP Host header attackes](https://docs.djangoproject.com/en/3.0/topics/security/#host-headers-virtual-hosting), NetBox will not permit access to the server via any other hostnames (or IPs).
This is a list of valid fully-qualified domain names (FQDNs) and/or IP addresses that can be used to reach the NetBox service. Usually this is the same as the hostname for the NetBox server, but can also be different; for example, when using a reverse proxy serving the NetBox website under a different FQDN than the hostname of the NetBox server. To help guard against [HTTP Host header attacks](https://docs.djangoproject.com/en/3.0/topics/security/#host-headers-virtual-hosting), NetBox will not permit access to the server via any other hostnames (or IPs).
!!! note
This parameter must always be defined as a list or tuple, even if only a single value is provided.

View File

@@ -2,7 +2,7 @@
Custom links allow users to display arbitrary hyperlinks to external content within NetBox object views. These are helpful for cross-referencing related records in systems outside NetBox. For example, you might create a custom link on the device view which links to the current device in a Network Monitoring System (NMS).
Custom links are created by navigating to Customization > Custom Links. Each link is associated with a particular NetBox object type (site, device, prefix, etc.) and will be displayed on relevant views. Each link has display text and a URL, and data from the NetBox item being viewed can be included in the link using [Jinja2 template code](https://jinja2docs.readthedocs.io/en/stable/) through the variable `object`, and custom fields through `object.cf`.
Custom links are created by navigating to Customization > Custom Links. Each link is associated with a particular NetBox object type (site, device, prefix, etc.) and will be displayed on relevant views. Each link has display text and a URL, and data from the NetBox item being viewed can be included in the link using [Jinja template code](https://jinja.palletsprojects.com/en/stable/) through the variable `object`, and custom fields through `object.cf`.
For example, you might define a link like this:

View File

@@ -8,6 +8,8 @@ This documentation describes the process of packaging and publishing a new NetBo
While major releases generally introduce some very substantial change to the application, they are typically treated the same as minor version increments for the purpose of release packaging.
For patch releases (e.g. upgrading from v4.2.2 to v4.2.3), begin at the [patch releases](#patch-releases) heading below. For minor or major releases, complete the entire checklist.
## Minor Version Releases
### Address Constrained Dependencies
@@ -85,7 +87,20 @@ In cases where upgrading a dependency to its most recent release is breaking, it
### Update UI Dependencies
Check whether any UI dependencies (JavaScript packages, fonts, etc.) need to be updated by running `yarn outdated` from within the `project-static/` directory. [Upgrade these dependencies](./web-ui.md#updating-dependencies) as necessary, then run `yarn bundle` to generate the necessary files for distribution.
Check whether any UI dependencies (JavaScript packages, fonts, etc.) need to be updated by running `yarn outdated` from within the `project-static/` directory. [Upgrade these dependencies](./web-ui.md#updating-dependencies) as necessary, then run `yarn bundle` to generate the necessary files for distribution:
```
$ yarn bundle
yarn run v1.22.19
$ node bundle.js
✅ Bundled source file 'styles/external.scss' to 'netbox-external.css'
✅ Bundled source file 'styles/netbox.scss' to 'netbox.css'
✅ Bundled source file 'styles/svg/rack_elevation.scss' to 'rack_elevation.css'
✅ Bundled source file 'styles/svg/cable_trace.scss' to 'cable_trace.css'
✅ Bundled source file 'index.ts' to 'netbox.js'
✅ Copied graphiql files
Done in 1.00s.
```
### Rebuild the Device Type Definition Schema
@@ -116,9 +131,12 @@ Then, compile these portable (`.po`) files for use in the application:
### Update Version and Changelog
* Update the version and published date in `release.yaml` with the current version & date. Add a designation (e.g.g `beta1`) if applicable.
* Update the version number and date in `netbox/release.yaml`. Add or remove the designation (e.g. `beta1`) if applicable.
* Update the example version numbers in the feature request and bug report templates under `.github/ISSUE_TEMPLATES/`.
* Replace the "FUTURE" placeholder in the release notes with the current date.
* Add a section for this release at the top of the changelog page for the minor version (e.g. `docs/release-notes/version-4.2.md`) listing all relevant changes made in this release.
!!! tip
Put yourself in the shoes of the user when recording change notes. Focus on the effect that each change has for the end user, rather than the specific bits of code that were modified in a PR. Ensure that each message conveys meaning absent context of the initial feature request or bug report. Remember to include key words or phrases (such as exception names) that can be easily searched.
### Submit a Pull Request
@@ -126,6 +144,9 @@ Commit the above changes and submit a pull request titled **"Release vX.Y.Z"** t
Once CI has completed and a colleague has reviewed the PR, merge it. This effects a new release in the `main` branch.
!!! warning
To ensure a streamlined review process, the pull request for a release **must** be limited to the changes outlined in this document. A release PR must never include functional changes to the application: Any unrelated "cleanup" needs to be captured in a separate PR prior to the release being shipped.
### Create a New Release
Create a [new release](https://github.com/netbox-community/netbox/releases/new) on GitHub with the following parameters.

View File

@@ -22,7 +22,7 @@ NetBox generally follows the [Django style guide](https://docs.djangoproject.com
### Linting
The [ruff](https://docs.astral.sh/ruff/) linter is used to enforce code style. A [pre-commit hook](./getting-started.md#3-enable-pre-commit-hooks) which runs this automatically is included with NetBox. To invoke `ruff` manually, run:
The [ruff](https://docs.astral.sh/ruff/) linter is used to enforce code style, and is run automatically by [pre-commit](./getting-started.md#5-install-pre-commit). To invoke `ruff` manually, run:
```
ruff check netbox/

View File

@@ -30,7 +30,7 @@ To download translated strings automatically, you'll need to:
1. Install the [Transifex CLI client](https://github.com/transifex/cli)
2. Generate a [Transifex API token](https://app.transifex.com/user/settings/api/)
Once you have the client set up, run the following command:
Once you have the client set up, run the following command from the project root (e.g. `/opt/netbox/`):
```no-highlight
TX_TOKEN=$TOKEN tx pull
@@ -46,6 +46,9 @@ Once retrieved, the updated strings need to be compiled into new `.mo` files so
Once any new `.mo` files have been generated, they need to be committed and pushed back up to GitHub. (Again, this is typically done as part of publishing a new NetBox release.)
!!! tip
Run `git status` to check that both `*.mo` & `*.po` files have been updated as expected.
## Proposing New Languages
If you'd like to add support for a new language to NetBox, the first step is to [submit a GitHub issue](https://github.com/netbox-community/netbox/issues/new?assignees=&labels=type%3A+translation&projects=&template=translation.yaml) to capture the proposal. While we'd like to add as many languages as possible, we do need to limit the rate at which new languages are added. New languages will be selected according to community interest and the number of volunteers who sign up as translators.

View File

@@ -46,7 +46,7 @@ Regions will always be listed alphabetically by name within each parent, and the
Like regions, site groups can be arranged in a recursive hierarchy for grouping sites. However, whereas regions are intended for geographic organization, site groups may be used for functional grouping. For example, you might classify sites as corporate, branch, or customer sites in addition to where they are physically located.
The use of both regions and site groups affords to independent but complementary dimensions across which sites can be organized.
The use of both regions and site groups affords two independent but complementary dimensions across which sites can be organized.
## Sites

View File

@@ -62,6 +62,9 @@ GRANT CREATE ON SCHEMA public TO netbox;
!!! danger "Use a strong password"
**Do not use the password from the example.** Choose a strong, random password to ensure secure database authentication for your NetBox installation.
!!! danger "Use UTF8 encoding"
Make sure that your database uses `UTF8` encoding (the default for new installations). Especially do not use `SQL_ASCII` encoding, as it can lead to unpredictable and unrecoverable errors. Enter `\l` to check your encoding.
Once complete, enter `\q` to exit the PostgreSQL shell.
## Verify Service Status

View File

@@ -21,7 +21,7 @@ The following sections detail how to set up a new instance of NetBox:
| Dependency | Supported Versions |
|------------|--------------------|
| Python | 3.10, 3.11, 3.12 |
| PostgreSQL | 12+ |
| PostgreSQL | 13+ |
| Redis | 4.0+ |
Below is a simplified overview of the NetBox application stack for reference:

View File

@@ -20,7 +20,7 @@ NetBox requires the following dependencies:
| Dependency | Supported Versions |
|------------|--------------------|
| Python | 3.10, 3.11, 3.12 |
| PostgreSQL | 12+ |
| PostgreSQL | 13+ |
| Redis | 4.0+ |
## 3. Install the Latest Release

View File

@@ -1,6 +1,6 @@
# GraphQL API Overview
NetBox provides a read-only [GraphQL](https://graphql.org/) API to complement its REST API. This API is powered by [Strawberry Django](https://strawberry-graphql.github.io/strawberry-django/).
NetBox provides a read-only [GraphQL](https://graphql.org/) API to complement its REST API. This API is powered by [Strawberry Django](https://strawberry.rocks/).
## Queries
@@ -47,7 +47,7 @@ NetBox provides both a singular and plural query field for each object type:
For example, query `device(id:123)` to fetch a specific device (identified by its unique ID), and query `device_list` (with an optional set of filters) to fetch all devices.
For more detail on constructing GraphQL queries, see the [GraphQL queries documentation](https://graphql.org/learn/queries/). For filtering and lookup syntax, please refer to the [Strawberry Django documentation](https://strawberry-graphql.github.io/strawberry-django/guide/filters/).
For more detail on constructing GraphQL queries, see the [GraphQL queries documentation](https://graphql.org/learn/queries/). For filtering and lookup syntax, please refer to the [Strawberry Django documentation](https://strawberry.rocks/docs/django/guide/filters).
## Filtering

View File

@@ -2,7 +2,7 @@
## What is a REST API?
REST stands for [representational state transfer](https://en.wikipedia.org/wiki/Representational_state_transfer). It's a particular type of API which employs HTTP requests and [JavaScript Object Notation (JSON)](https://www.json.org/) to facilitate create, retrieve, update, and delete (CRUD) operations on objects within an application. Each type of operation is associated with a particular HTTP verb:
REST stands for [representational state transfer](https://en.wikipedia.org/wiki/REST). It's a particular type of API which employs HTTP requests and [JavaScript Object Notation (JSON)](https://www.json.org/) to facilitate create, retrieve, update, and delete (CRUD) operations on objects within an application. Each type of operation is associated with a particular HTTP verb:
* `GET`: Retrieve an object or list of objects
* `POST`: Create an object

View File

@@ -1,5 +1,72 @@
# NetBox v4.2
## v4.2.4 (2025-02-21)
### Enhancements
* [#17309](https://github.com/netbox-community/netbox/issues/17309) - Omit empty counts in related object tables
* [#18277](https://github.com/netbox-community/netbox/issues/18277) - Improve multi-table inheritance in serialization of change-logged models
* [#18286](https://github.com/netbox-community/netbox/issues/18286) - Add more job duration choices
* [#18357](https://github.com/netbox-community/netbox/issues/18357) - Display author name in plugin list for locally installed plugins
* [#18408](https://github.com/netbox-community/netbox/issues/18408) - Add Paused status for virtual machines
* [#18584](https://github.com/netbox-community/netbox/issues/18584) - Add rack type column to manufacturer list
### Bug Fixes
* [#17436](https://github.com/netbox-community/netbox/issues/17436) - Fix {module} replacement in module bays
* [#18013](https://github.com/netbox-community/netbox/issues/18013) - Limit object type to selected object in change log filter
* [#18241](https://github.com/netbox-community/netbox/issues/18241) - Default logging level of custom scripts changed to INFO
* [#18247](https://github.com/netbox-community/netbox/issues/18247) - Fix visibility of disabled cable paths in dark mode
* [#18480](https://github.com/netbox-community/netbox/issues/18480) - Clean data passed to script in runscript command
* [#18555](https://github.com/netbox-community/netbox/issues/18555) - Add default get_absolute_url method to plugin models
* [#18585](https://github.com/netbox-community/netbox/issues/18585) - Fix filtering circuits by location
* [#18593](https://github.com/netbox-community/netbox/issues/18593) - Fix "Create & Add Another" IP Address workflow
* [#18594](https://github.com/netbox-community/netbox/issues/18594) - Enable sorting by ASN count on site and provider lists
* [#18619](https://github.com/netbox-community/netbox/issues/18619) - Ensure shift-click selection selects only visible list items
* [#18674](https://github.com/netbox-community/netbox/issues/18674) - Preserve form values when selecting speed on circuit termination
---
## v4.2.3 (2025-02-04)
### Enhancements
* [#18518](https://github.com/netbox-community/netbox/issues/18518) - Add a "hostname" `<meta>` tag to the page header
### Bug Fixes
* [#18497](https://github.com/netbox-community/netbox/issues/18497) - Fix unhandled `FieldDoesNotExist` exception when search results include virtual circuit
* [#18433](https://github.com/netbox-community/netbox/issues/18433) - Fix MAC address not shown as "primary for interface" in MAC address detail view
* [#18154](https://github.com/netbox-community/netbox/issues/18154) - Allow anonymous users to change default table preferences
* [#18515](https://github.com/netbox-community/netbox/issues/18515) - Fix Django `collectstatic` management command in debug mode with Redis not running
* [#18456](https://github.com/netbox-community/netbox/issues/18456) - Avoid duplicate MAC Address column in interface tables
* [#18447](https://github.com/netbox-community/netbox/issues/18447) - Fix `FieldError` exception when sorting interface tables on MAC Address columns
* [#18438](https://github.com/netbox-community/netbox/issues/18438) - Improve performance in IPAM migration `0072_prefix_cached_relations` when upgrading from v4.1 or earlier
* [#18436](https://github.com/netbox-community/netbox/issues/18436) - Reset primary MAC address when unassigning MAC address from interface
* [#18181](https://github.com/netbox-community/netbox/issues/18181) - Fix "Create & Add Another" workflow when adding IP addresses to interfaces
---
## v4.2.2 (2025-01-17)
### Bug Fixes
* [#18336](https://github.com/netbox-community/netbox/issues/18336) - Validate new rack height against installed devices when changing a rack's type
* [#18350](https://github.com/netbox-community/netbox/issues/18350) - Fix `FieldDoesNotExist` exception when global search results include a circuit termination
* [#18353](https://github.com/netbox-community/netbox/issues/18353) - Disable fetching of plugin catalog data when `ISOLATED_DEPLOYMENT` is enabled
* [#18362](https://github.com/netbox-community/netbox/issues/18362) - Avoid transmitting census data on every worker restart
* [#18363](https://github.com/netbox-community/netbox/issues/18363) - Fix support for assigning a MAC address to an interface via the REST API
* [#18368](https://github.com/netbox-community/netbox/issues/18368) - Restore missing attributes from REST API serializer for MAC addresses (`tags`, `created`, `last_updated`, and custom fields)
* [#18369](https://github.com/netbox-community/netbox/issues/18369) - Fix `TypeError` exception when rendering the system configuration view with one or more custom classes defined under `PROTECTION_RULES`
* [#18373](https://github.com/netbox-community/netbox/issues/18373) - Fix `AttributeError` exception when attempting to assign host devices to a cluster
* [#18376](https://github.com/netbox-community/netbox/issues/18376) - Fix the display of tagged VLANs in interfaces list for Q-in-Q interfaces
* [#18379](https://github.com/netbox-community/netbox/issues/18379) - Ensure RSS feed dashboard widget content is sanitized
* [#18392](https://github.com/netbox-community/netbox/issues/18392) - Virtual machines should not inherit config contexts assigned to locations
* [#18400](https://github.com/netbox-community/netbox/issues/18400) - Fix support for `STORAGE_BACKEND` configuration parameter
* [#18406](https://github.com/netbox-community/netbox/issues/18406) - Scope column headers in object lists should not be orderable
---
## v4.2.1 (2025-01-08)
### Bug Fixes

View File

@@ -64,6 +64,8 @@ markdown_extensions:
format: !!python/name:pymdownx.superfences.fence_code_format
- pymdownx.tabbed:
alternate_style: true
not_in_nav: |
/index.md
nav:
- Introduction: 'introduction.md'
- Features:

View File

@@ -234,6 +234,11 @@ class CircuitFilterSet(NetBoxModelFilterSet, TenancyFilterSet, ContactModelFilte
to_field_name='slug',
label=_('Site (slug)'),
)
location_id = django_filters.ModelMultipleChoiceFilter(
field_name='terminations___location',
label=_('Location (ID)'),
queryset=Location.objects.all(),
)
termination_a_id = django_filters.ModelMultipleChoiceFilter(
queryset=CircuitTermination.objects.all(),
label=_('Termination A (ID)'),

View File

@@ -126,7 +126,7 @@ class CircuitFilterForm(TenancyFilterForm, ContactModelFilterForm, NetBoxModelFi
'type_id', 'status', 'install_date', 'termination_date', 'commit_rate', 'distance', 'distance_unit',
name=_('Attributes')
),
FieldSet('region_id', 'site_group_id', 'site_id', name=_('Location')),
FieldSet('region_id', 'site_group_id', 'site_id', 'location_id', name=_('Location')),
FieldSet('tenant_group_id', 'tenant_id', name=_('Tenant')),
FieldSet('contact', 'contact_role', 'contact_group', name=_('Contacts')),
)
@@ -181,6 +181,11 @@ class CircuitFilterForm(TenancyFilterForm, ContactModelFilterForm, NetBoxModelFi
},
label=_('Site')
)
location_id = DynamicModelMultipleChoiceField(
queryset=Location.objects.all(),
required=False,
label=_('Location')
)
install_date = forms.DateField(
label=_('Install date'),
required=False,

View File

@@ -1,4 +1,3 @@
# Generated by Django 5.0.9 on 2024-10-21 17:34
import django.db.models.deletion
from django.db import migrations, models
@@ -16,7 +15,7 @@ def populate_denormalized_fields(apps, schema_editor):
termination._site_id = termination.site_id
# Note: Location cannot be set prior to migration
CircuitTermination.objects.bulk_update(terminations, ['_region', '_site_group', '_site'])
CircuitTermination.objects.bulk_update(terminations, ['_region', '_site_group', '_site'], batch_size=100)
class Migration(migrations.Migration):

View File

@@ -34,7 +34,7 @@ class CircuitTerminationIndex(SearchIndex):
('port_speed', 2000),
('upstream_speed', 2000),
)
display_attrs = ('circuit', 'site', 'provider_network', 'description')
display_attrs = ('circuit', 'termination', 'description')
@register_search
@@ -90,7 +90,7 @@ class VirtualCircuitIndex(SearchIndex):
('description', 500),
('comments', 5000),
)
display_attrs = ('provider', 'provider_network', 'provider_account', 'status', 'tenant', 'description')
display_attrs = ('provider_network', 'provider_account', 'status', 'tenant', 'description')
@register_search

View File

@@ -33,7 +33,6 @@ class ProviderTable(ContactsColumnMixin, NetBoxTable):
verbose_name=_('ASNs')
)
asn_count = columns.LinkedCountColumn(
accessor=tables.A('asns__count'),
viewname='ipam:asn_list',
url_params={'provider_id': 'pk'},
verbose_name=_('ASN Count')

View File

@@ -3,8 +3,10 @@ from django.test import TestCase
from circuits.choices import *
from circuits.filtersets import *
from circuits.models import *
from dcim.choices import InterfaceTypeChoices
from dcim.models import Cable, Device, DeviceRole, DeviceType, Interface, Manufacturer, Region, Site, SiteGroup
from dcim.choices import InterfaceTypeChoices, LocationStatusChoices
from dcim.models import (
Cable, Device, DeviceRole, DeviceType, Interface, Location, Manufacturer, Region, Site, SiteGroup
)
from ipam.models import ASN, RIR
from netbox.choices import DistanceUnitChoices
from tenancy.models import Tenant, TenantGroup
@@ -225,6 +227,17 @@ class CircuitTestCase(TestCase, ChangeLoggedFilterSetTests):
)
ProviderNetwork.objects.bulk_create(provider_networks)
locations = (
Location.objects.create(
site=sites[0], name='Test Location 1', slug='test-location-1',
status=LocationStatusChoices.STATUS_ACTIVE,
),
Location.objects.create(
site=sites[1], name='Test Location 2', slug='test-location-2',
status=LocationStatusChoices.STATUS_ACTIVE,
),
)
circuits = (
Circuit(
provider=providers[0],
@@ -305,7 +318,9 @@ class CircuitTestCase(TestCase, ChangeLoggedFilterSetTests):
circuit_terminations = ((
CircuitTermination(circuit=circuits[0], termination=sites[0], term_side='A'),
CircuitTermination(circuit=circuits[0], termination=locations[0], term_side='Z'),
CircuitTermination(circuit=circuits[1], termination=sites[1], term_side='A'),
CircuitTermination(circuit=circuits[1], termination=locations[1], term_side='Z'),
CircuitTermination(circuit=circuits[2], termination=sites[2], term_side='A'),
CircuitTermination(circuit=circuits[3], termination=provider_networks[0], term_side='A'),
CircuitTermination(circuit=circuits[4], termination=provider_networks[1], term_side='A'),
@@ -395,6 +410,11 @@ class CircuitTestCase(TestCase, ChangeLoggedFilterSetTests):
params = {'site': [sites[0].slug, sites[1].slug]}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
def test_location(self):
location_ids = Location.objects.values_list('id', flat=True)[:2]
params = {'location_id': location_ids}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
def test_tenant(self):
tenants = Tenant.objects.all()[:2]
params = {'tenant_id': [tenants[0].pk, tenants[1].pk]}

View File

@@ -4,6 +4,7 @@ from django.shortcuts import get_object_or_404, redirect, render
from django.utils.translation import gettext_lazy as _
from dcim.views import PathTraceView
from ipam.models import ASN
from netbox.views import generic
from tenancy.views import ObjectContactsView
from utilities.forms import ConfirmationForm
@@ -20,7 +21,8 @@ from .models import *
@register_model_view(Provider, 'list', path='', detail=False)
class ProviderListView(generic.ObjectListView):
queryset = Provider.objects.annotate(
count_circuits=count_related(Circuit, 'provider')
count_circuits=count_related(Circuit, 'provider'),
asn_count=count_related(ASN, 'providers'),
)
filterset = filtersets.ProviderFilterSet
filterset_form = forms.ProviderFilterForm

View File

@@ -28,4 +28,7 @@ class CoreConfig(AppConfig):
# Clear Redis cache on startup in development mode
if settings.DEBUG:
cache.clear()
try:
cache.clear()
except Exception:
pass

View File

@@ -81,8 +81,10 @@ class JobIntervalChoices(ChoiceSet):
CHOICES = (
(INTERVAL_MINUTELY, _('Minutely')),
(INTERVAL_HOURLY, _('Hourly')),
(INTERVAL_HOURLY * 12, _('12 hours')),
(INTERVAL_DAILY, _('Daily')),
(INTERVAL_WEEKLY, _('Weekly')),
(INTERVAL_DAILY * 30, _('30 days')),
)

View File

@@ -62,6 +62,7 @@ class DataFileFilterForm(NetBoxModelFilterSetForm):
class JobFilterForm(SavedFiltersMixin, FilterForm):
model = Job
fieldsets = (
FieldSet('q', 'filter_id'),
FieldSet('object_type', 'status', name=_('Attributes')),
@@ -162,6 +163,7 @@ class ObjectChangeFilterForm(SavedFiltersMixin, FilterForm):
class ConfigRevisionFilterForm(SavedFiltersMixin, FilterForm):
model = ConfigRevision
fieldsets = (
FieldSet('q', 'filter_id'),
)

View File

@@ -1,8 +1,11 @@
import logging
import requests
import sys
from netbox.jobs import JobRunner
from django.conf import settings
from netbox.jobs import JobRunner, system_job
from netbox.search.backends import search_backend
from .choices import DataSourceStatusChoices
from .choices import DataSourceStatusChoices, JobIntervalChoices
from .exceptions import SyncError
from .models import DataSource
@@ -31,3 +34,44 @@ class SyncDataSourceJob(JobRunner):
if type(e) is SyncError:
logging.error(e)
raise e
@system_job(interval=JobIntervalChoices.INTERVAL_DAILY)
class SystemHousekeepingJob(JobRunner):
"""
Perform daily system housekeeping functions.
"""
class Meta:
name = "System Housekeeping"
def run(self, *args, **kwargs):
# Skip if running in development or test mode
if settings.DEBUG or 'test' in sys.argv:
return
# TODO: Migrate other housekeeping functions from the `housekeeping` management command.
self.send_census_report()
@staticmethod
def send_census_report():
"""
Send a census report (if enabled).
"""
# Skip if census reporting is disabled
if settings.ISOLATED_DEPLOYMENT or not settings.CENSUS_REPORTING_ENABLED:
return
census_data = {
'version': settings.RELEASE.full_version,
'python_version': sys.version.split()[0],
'deployment_id': settings.DEPLOYMENT_ID,
}
try:
requests.get(
url=settings.CENSUS_URL,
params=census_data,
timeout=3,
proxies=settings.HTTP_PROXIES
)
except requests.exceptions.RequestException:
pass

View File

@@ -80,6 +80,13 @@ def get_local_plugins(plugins=None):
plugin = importlib.import_module(plugin_name)
plugin_config: PluginConfig = plugin.config
if plugin_config.author:
author = PluginAuthor(
name=plugin_config.author,
)
else:
author = None
local_plugins[plugin_config.name] = Plugin(
config_name=plugin_config.name,
title_short=plugin_config.verbose_name,
@@ -88,6 +95,7 @@ def get_local_plugins(plugins=None):
description_short=plugin_config.description,
is_local=True,
is_installed=True,
author=author,
installed_version=plugin_config.version,
)

View File

@@ -570,8 +570,9 @@ class SystemView(UserPassesTestMixin, View):
return response
# Serialize any CustomValidator classes
if hasattr(config, 'CUSTOM_VALIDATORS') and config.CUSTOM_VALIDATORS:
config.CUSTOM_VALIDATORS = json.dumps(config.CUSTOM_VALIDATORS, cls=ConfigJSONEncoder, indent=4)
for attr in ['CUSTOM_VALIDATORS', 'PROTECTION_RULES']:
if hasattr(config, attr) and getattr(config, attr, None):
setattr(config, attr, json.dumps(getattr(config, attr), cls=ConfigJSONEncoder, indent=4))
return render(request, 'core/system.html', {
'stats': stats,
@@ -594,7 +595,7 @@ class BasePluginView(UserPassesTestMixin, View):
catalog_plugins_error = cache.get(self.CACHE_KEY_CATALOG_ERROR, default=False)
if not catalog_plugins_error:
catalog_plugins = get_catalog_plugins()
if not catalog_plugins:
if not catalog_plugins and not settings.ISOLATED_DEPLOYMENT:
# Cache for 5 minutes to avoid spamming connection
cache.set(self.CACHE_KEY_CATALOG_ERROR, True, 300)
messages.warning(request, _("Plugins catalog could not be loaded"))

View File

@@ -170,8 +170,8 @@ class MACAddressSerializer(NetBoxModelSerializer):
class Meta:
model = MACAddress
fields = [
'id', 'url', 'display_url', 'display', 'mac_address', 'assigned_object_type', 'assigned_object',
'description', 'comments',
'id', 'url', 'display_url', 'display', 'mac_address', 'assigned_object_type', 'assigned_object_id',
'assigned_object', 'description', 'comments', 'tags', 'custom_fields', 'created', 'last_updated',
]
brief_fields = ('id', 'url', 'display', 'mac_address', 'description')

View File

@@ -53,10 +53,10 @@ class ScopedFilterSet(BaseFilterSet):
label=_('Site (slug)'),
)
location_id = TreeNodeMultipleChoiceFilter(
queryset=Location.objects.all(),
field_name='_location',
lookup_expr='in',
label=_('Location (ID)'),
queryset=Location.objects.all(),
field_name='_location',
lookup_expr='in',
label=_('Location (ID)'),
)
location = TreeNodeMultipleChoiceFilter(
queryset=Location.objects.all(),

View File

@@ -1652,8 +1652,8 @@ class MACAddressFilterSet(NetBoxModelFilterSet):
if not value.strip():
return queryset
qs_filter = (
Q(mac_address__icontains=value) |
Q(description__icontains=value)
Q(mac_address__icontains=value) |
Q(description__icontains=value)
)
return queryset.filter(qs_filter)

View File

@@ -303,7 +303,7 @@ class RackTypeFilterForm(RackBaseFilterForm):
model = RackType
fieldsets = (
FieldSet('q', 'filter_id', 'tag'),
FieldSet('form_factor', 'width', 'u_height', name=_('Rack Type')),
FieldSet('manufacturer_id', 'form_factor', 'width', 'u_height', name=_('Rack Type')),
FieldSet('starting_unit', 'desc_units', name=_('Numbering')),
FieldSet('weight', 'max_weight', 'weight_unit', name=_('Weight')),
)

View File

@@ -1810,6 +1810,11 @@ class MACAddressForm(NetBoxModelForm):
super().__init__(*args, **kwargs)
if instance and instance.assigned_object and instance.assigned_object.primary_mac_address:
if instance.assigned_object.primary_mac_address.pk == instance.pk:
self.fields['interface'].disabled = True
self.fields['vminterface'].disabled = True
def clean(self):
super().clean()

View File

@@ -15,6 +15,7 @@ from django.urls import reverse
from django.utils.safestring import mark_safe
from django.utils.translation import gettext_lazy as _
from core.models import ObjectType
from dcim.choices import *
from dcim.constants import *
from dcim.fields import MACAddressField
@@ -1297,6 +1298,7 @@ class Module(PrimaryModel, ConfigContextModel):
else:
# ModuleBays must be saved individually for MPTT
for instance in create_instances:
instance.name = instance.name.replace(MODULE_TOKEN, str(self.module_bay.position))
instance.save()
update_fields = ['module']
@@ -1522,3 +1524,34 @@ class MACAddress(PrimaryModel):
def __str__(self):
return str(self.mac_address)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# Denote the original assigned object (if any) for validation in clean()
self._original_assigned_object_id = self.__dict__.get('assigned_object_id')
self._original_assigned_object_type_id = self.__dict__.get('assigned_object_type_id')
@cached_property
def is_primary(self):
if self.assigned_object and hasattr(self.assigned_object, 'primary_mac_address'):
if self.assigned_object.primary_mac_address and self.assigned_object.primary_mac_address.pk == self.pk:
return True
return False
def clean(self, *args, **kwargs):
super().clean()
if self._original_assigned_object_id and self._original_assigned_object_type_id:
assigned_object = self.assigned_object
ct = ObjectType.objects.get_for_id(self._original_assigned_object_type_id)
original_assigned_object = ct.get_object_for_this_type(pk=self._original_assigned_object_id)
if original_assigned_object.primary_mac_address:
if not assigned_object:
raise ValidationError(
_("Cannot unassign MAC Address while it is designated as the primary MAC for an object")
)
elif original_assigned_object != assigned_object:
raise ValidationError(
_("Cannot reassign MAC Address while it is designated as the primary MAC for an object")
)

View File

@@ -374,22 +374,27 @@ class Rack(ContactsMixin, ImageAttachmentsMixin, RackBase):
if not self._state.adding:
mounted_devices = Device.objects.filter(rack=self).exclude(position__isnull=True).order_by('position')
effective_u_height = self.rack_type.u_height if self.rack_type else self.u_height
effective_starting_unit = self.rack_type.starting_unit if self.rack_type else self.starting_unit
# Validate that Rack is tall enough to house the highest mounted Device
if top_device := mounted_devices.last():
min_height = top_device.position + top_device.device_type.u_height - self.starting_unit
if self.u_height < min_height:
min_height = top_device.position + top_device.device_type.u_height - effective_starting_unit
if effective_u_height < min_height:
field = 'rack_type' if self.rack_type else 'u_height'
raise ValidationError({
'u_height': _(
field: _(
"Rack must be at least {min_height}U tall to house currently installed devices."
).format(min_height=min_height)
})
# Validate that the Rack's starting unit is less than or equal to the position of the lowest mounted Device
if last_device := mounted_devices.first():
if self.starting_unit > last_device.position:
if effective_starting_unit > last_device.position:
field = 'rack_type' if self.rack_type else 'starting_unit'
raise ValidationError({
'starting_unit': _("Rack unit numbering must begin at {position} or less to house "
"currently installed devices.").format(position=last_device.position)
field: _("Rack unit numbering must begin at {position} or less to house "
"currently installed devices.").format(position=last_device.position)
})
# Validate that Rack was assigned a Location of its same site, if applicable

View File

@@ -705,7 +705,7 @@ class DeviceInterfaceTable(InterfaceTable):
model = models.Interface
fields = (
'pk', 'id', 'name', 'module_bay', 'module', 'label', 'enabled', 'type', 'parent', 'bridge', 'lag',
'mgmt_only', 'mtu', 'mode', 'mac_address', 'wwn', 'rf_role', 'rf_channel', 'rf_channel_frequency',
'mgmt_only', 'mtu', 'mode', 'primary_mac_address', 'wwn', 'rf_role', 'rf_channel', 'rf_channel_frequency',
'rf_channel_width', 'tx_power', 'description', 'mark_connected', 'cable', 'cable_color', 'wireless_link',
'wireless_lans', 'link_peer', 'connection', 'tags', 'vdcs', 'vrf', 'l2vpn', 'tunnel', 'ip_addresses',
'fhrp_groups', 'untagged_vlan', 'tagged_vlans', 'qinq_svlan', 'actions',

View File

@@ -31,6 +31,11 @@ class ManufacturerTable(ContactsColumnMixin, NetBoxTable):
verbose_name=_('Name'),
linkify=True
)
racktype_count = columns.LinkedCountColumn(
viewname='dcim:racktype_list',
url_params={'manufacturer_id': 'pk'},
verbose_name=_('Rack Types')
)
devicetype_count = columns.LinkedCountColumn(
viewname='dcim:devicetype_list',
url_params={'manufacturer_id': 'pk'},
@@ -58,12 +63,12 @@ class ManufacturerTable(ContactsColumnMixin, NetBoxTable):
class Meta(NetBoxTable.Meta):
model = models.Manufacturer
fields = (
'pk', 'id', 'name', 'devicetype_count', 'moduletype_count', 'inventoryitem_count', 'platform_count',
'description', 'slug', 'tags', 'contacts', 'actions', 'created', 'last_updated',
'pk', 'id', 'name', 'racktype_count', 'devicetype_count', 'moduletype_count', 'inventoryitem_count',
'platform_count', 'description', 'slug', 'tags', 'contacts', 'actions', 'created', 'last_updated',
)
default_columns = (
'pk', 'name', 'devicetype_count', 'moduletype_count', 'inventoryitem_count', 'platform_count',
'description', 'slug',
'pk', 'name', 'racktype_count', 'devicetype_count', 'moduletype_count', 'inventoryitem_count',
'platform_count', 'description', 'slug',
)

View File

@@ -94,7 +94,6 @@ class SiteTable(TenancyColumnsMixin, ContactsColumnMixin, NetBoxTable):
verbose_name=_('ASNs')
)
asn_count = columns.LinkedCountColumn(
accessor=tables.A('asns__count'),
viewname='ipam:asn_list',
url_params={'site_id': 'pk'},
verbose_name=_('ASN Count')

View File

@@ -69,16 +69,18 @@ INTERFACE_FHRPGROUPS = """
"""
INTERFACE_TAGGED_VLANS = """
{% if record.mode == 'tagged' %}
{% load i18n %}
{% if record.mode == 'access' %}
{% elif record.mode == 'tagged-all' %}
{% trans "All" %}
{% else %}
{% if value.count > 3 %}
<a href="{% url 'ipam:vlan_list' %}?{{ record|meta:"model_name" }}_id={{ record.pk }}">{{ value.count }} VLANs</a>
{% else %}
{% for vlan in value.all %}
<a href="{{ vlan.get_absolute_url }}">{{ vlan }}</a><br />
<a href="{{ vlan.get_absolute_url }}">{{ vlan }}</a><br />
{% endfor %}
{% endif %}
{% elif record.mode == 'tagged-all' %}
All
{% endif %}
"""
@@ -157,8 +159,8 @@ CONSOLEPORT_BUTTONS = """
</span>
{% endif %}
{% elif perms.dcim.add_cable %}
<a href="#" class="btn btn-outline-dark btn-sm disabled"><i class="mdi mdi-transit-connection-variant" aria-hidden="true"></i></a>
<a href="#" class="btn btn-outline-dark btn-sm disabled"><i class="mdi mdi-lan-connect" aria-hidden="true"></i></a>
<a href="#" class="btn btn-outline-secondary btn-sm disabled"><i class="mdi mdi-transit-connection-variant" aria-hidden="true"></i></a>
<a href="#" class="btn btn-outline-secondary btn-sm disabled"><i class="mdi mdi-lan-connect" aria-hidden="true"></i></a>
<span class="dropdown">
<button type="button" class="btn btn-success btn-sm dropdown-toggle" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="mdi mdi-ethernet-cable" aria-hidden="true"></span>
@@ -170,7 +172,7 @@ CONSOLEPORT_BUTTONS = """
</ul>
</span>
{% else %}
<a href="#" class="btn btn-outline-dark btn-sm disabled"><i class="mdi mdi-ethernet-cable" aria-hidden="true"></i></a>
<a href="#" class="btn btn-outline-secondary btn-sm disabled"><i class="mdi mdi-ethernet-cable" aria-hidden="true"></i></a>
{% endif %}
"""
@@ -207,8 +209,8 @@ CONSOLESERVERPORT_BUTTONS = """
</span>
{% endif %}
{% elif perms.dcim.add_cable %}
<a href="#" class="btn btn-outline-dark btn-sm disabled"><i class="mdi mdi-transit-connection-variant" aria-hidden="true"></i></a>
<a href="#" class="btn btn-outline-dark btn-sm disabled"><i class="mdi mdi-lan-connect" aria-hidden="true"></i></a>
<a href="#" class="btn btn-outline-secondary btn-sm disabled"><i class="mdi mdi-transit-connection-variant" aria-hidden="true"></i></a>
<a href="#" class="btn btn-outline-secondary btn-sm disabled"><i class="mdi mdi-lan-connect" aria-hidden="true"></i></a>
<span class="dropdown">
<button type="button" class="btn btn-success btn-sm dropdown-toggle" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="mdi mdi-ethernet-cable" aria-hidden="true"></span>
@@ -220,7 +222,7 @@ CONSOLESERVERPORT_BUTTONS = """
</ul>
</span>
{% else %}
<a href="#" class="btn btn-outline-dark btn-sm disabled"><i class="mdi mdi-ethernet-cable" aria-hidden="true"></i></a>
<a href="#" class="btn btn-outline-secondary btn-sm disabled"><i class="mdi mdi-ethernet-cable" aria-hidden="true"></i></a>
{% endif %}
"""
@@ -257,8 +259,8 @@ POWERPORT_BUTTONS = """
</span>
{% endif %}
{% elif perms.dcim.add_cable %}
<a href="#" class="btn btn-outline-dark btn-sm disabled"><i class="mdi mdi-transit-connection-variant" aria-hidden="true"></i></a>
<a href="#" class="btn btn-outline-dark btn-sm disabled"><i class="mdi mdi-lan-connect" aria-hidden="true"></i></a>
<a href="#" class="btn btn-outline-secondary btn-sm disabled"><i class="mdi mdi-transit-connection-variant" aria-hidden="true"></i></a>
<a href="#" class="btn btn-outline-secondary btn-sm disabled"><i class="mdi mdi-lan-connect" aria-hidden="true"></i></a>
<span class="dropdown">
<button type="button" class="btn btn-success btn-sm dropdown-toggle" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="mdi mdi-ethernet-cable" aria-hidden="true"></span>
@@ -269,7 +271,7 @@ POWERPORT_BUTTONS = """
</ul>
</span>
{% else %}
<a href="#" class="btn btn-outline-dark btn-sm disabled"><i class="mdi mdi-ethernet-cable" aria-hidden="true"></i></a>
<a href="#" class="btn btn-outline-secondary btn-sm disabled"><i class="mdi mdi-ethernet-cable" aria-hidden="true"></i></a>
{% endif %}
"""
@@ -306,14 +308,14 @@ POWEROUTLET_BUTTONS = """
</span>
{% endif %}
{% elif perms.dcim.add_cable %}
<a href="#" class="btn btn-outline-dark btn-sm disabled"><i class="mdi mdi-transit-connection-variant" aria-hidden="true"></i></a>
<a href="#" class="btn btn-outline-dark btn-sm disabled"><i class="mdi mdi-lan-connect" aria-hidden="true"></i></a>
<a href="#" class="btn btn-outline-secondary btn-sm disabled"><i class="mdi mdi-transit-connection-variant" aria-hidden="true"></i></a>
<a href="#" class="btn btn-outline-secondary btn-sm disabled"><i class="mdi mdi-lan-connect" aria-hidden="true"></i></a>
{% if not record.mark_connected %}
<a href="{% url 'dcim:cable_add' %}?a_terminations_type=dcim.poweroutlet&a_terminations={{ record.pk }}&b_terminations_type=dcim.powerport&termination_b_site={{ object.site.pk }}&termination_b_rack={{ object.rack.pk }}&return_url={% url 'dcim:device_poweroutlets' pk=object.pk %}" title="Connect" class="btn btn-success btn-sm">
<i class="mdi mdi-ethernet-cable" aria-hidden="true"></i>
</a>
{% else %}
<a href="#" class="btn btn-outline-dark btn-sm disabled"><i class="mdi mdi-ethernet-cable" aria-hidden="true"></i></a>
<a href="#" class="btn btn-outline-secondary btn-sm disabled"><i class="mdi mdi-ethernet-cable" aria-hidden="true"></i></a>
{% endif %}
{% endif %}
"""
@@ -400,8 +402,8 @@ INTERFACE_BUTTONS = """
</a>
{% endif %}
{% elif record.is_wired and perms.dcim.add_cable %}
<a href="#" class="btn btn-outline-dark btn-sm disabled"><i class="mdi mdi-transit-connection-variant" aria-hidden="true"></i></a>
<a href="#" class="btn btn-outline-dark btn-sm disabled"><i class="mdi mdi-lan-connect" aria-hidden="true"></i></a>
<a href="#" class="btn btn-outline-secondary btn-sm disabled"><i class="mdi mdi-transit-connection-variant" aria-hidden="true"></i></a>
<a href="#" class="btn btn-outline-secondary btn-sm disabled"><i class="mdi mdi-lan-connect" aria-hidden="true"></i></a>
{% if not record.mark_connected %}
<span class="dropdown">
<button type="button" class="btn btn-success btn-sm dropdown-toggle" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false" title="Connect cable">
@@ -415,7 +417,7 @@ INTERFACE_BUTTONS = """
</ul>
</span>
{% else %}
<a href="#" class="btn btn-outline-dark btn-sm disabled"><i class="mdi mdi-ethernet-cable" aria-hidden="true"></i></a>
<a href="#" class="btn btn-outline-secondary btn-sm disabled"><i class="mdi mdi-ethernet-cable" aria-hidden="true"></i></a>
{% endif %}
{% elif record.is_wireless and perms.wireless.add_wirelesslink %}
<a href="{% url 'wireless:wirelesslink_add' %}?site_a={{ record.device.site.pk }}&location_a={{ record.device.location.pk }}&device_a={{ record.device_id }}&interface_a={{ record.pk }}&site_b={{ record.device.site.pk }}&location_b={{ record.device.location.pk }}" class="btn btn-success btn-sm">
@@ -457,8 +459,8 @@ FRONTPORT_BUTTONS = """
</span>
{% endif %}
{% elif perms.dcim.add_cable %}
<a href="#" class="btn btn-outline-dark btn-sm disabled"><i class="mdi mdi-transit-connection-variant" aria-hidden="true"></i></a>
<a href="#" class="btn btn-outline-dark btn-sm disabled"><i class="mdi mdi-lan-connect" aria-hidden="true"></i></a>
<a href="#" class="btn btn-outline-secondary btn-sm disabled"><i class="mdi mdi-transit-connection-variant" aria-hidden="true"></i></a>
<a href="#" class="btn btn-outline-secondary btn-sm disabled"><i class="mdi mdi-lan-connect" aria-hidden="true"></i></a>
{% if not record.mark_connected %}
<span class="dropdown">
<button type="button" class="btn btn-success btn-sm dropdown-toggle" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
@@ -474,7 +476,7 @@ FRONTPORT_BUTTONS = """
</ul>
</span>
{% else %}
<a href="#" class="btn btn-outline-dark btn-sm disabled"><i class="mdi mdi-ethernet-cable" aria-hidden="true"></i></a>
<a href="#" class="btn btn-outline-secondary btn-sm disabled"><i class="mdi mdi-ethernet-cable" aria-hidden="true"></i></a>
{% endif %}
{% endif %}
"""
@@ -512,8 +514,8 @@ REARPORT_BUTTONS = """
</span>
{% endif %}
{% elif perms.dcim.add_cable %}
<a href="#" class="btn btn-outline-dark btn-sm disabled"><i class="mdi mdi-transit-connection-variant" aria-hidden="true"></i></a>
<a href="#" class="btn btn-outline-dark btn-sm disabled"><i class="mdi mdi-lan-connect" aria-hidden="true"></i></a>
<a href="#" class="btn btn-outline-secondary btn-sm disabled"><i class="mdi mdi-transit-connection-variant" aria-hidden="true"></i></a>
<a href="#" class="btn btn-outline-secondary btn-sm disabled"><i class="mdi mdi-lan-connect" aria-hidden="true"></i></a>
{% if not record.mark_connected %}
<span class="dropdown">
<button type="button" class="btn btn-success btn-sm dropdown-toggle" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
@@ -529,7 +531,7 @@ REARPORT_BUTTONS = """
</ul>
</span>
{% else %}
<a href="#" class="btn btn-outline-dark btn-sm disabled"><i class="mdi mdi-ethernet-cable" aria-hidden="true"></i></a>
<a href="#" class="btn btn-outline-secondary btn-sm disabled"><i class="mdi mdi-ethernet-cable" aria-hidden="true"></i></a>
{% endif %}
{% endif %}
"""

View File

@@ -2447,3 +2447,46 @@ class VirtualDeviceContextTest(APIViewTestCases.APIViewTestCase):
# Omit identifier to test uniqueness constraint
},
]
class MACAddressTest(APIViewTestCases.APIViewTestCase):
model = MACAddress
brief_fields = ['description', 'display', 'id', 'mac_address', 'url']
bulk_update_data = {
'description': 'New description',
}
@classmethod
def setUpTestData(cls):
device = create_test_device(name='Device 1')
interfaces = (
Interface(device=device, name='Interface 1', type='1000base-t'),
Interface(device=device, name='Interface 2', type='1000base-t'),
Interface(device=device, name='Interface 3', type='1000base-t'),
Interface(device=device, name='Interface 4', type='1000base-t'),
Interface(device=device, name='Interface 5', type='1000base-t'),
)
Interface.objects.bulk_create(interfaces)
mac_addresses = (
MACAddress(mac_address='00:00:00:00:00:01', assigned_object=interfaces[0]),
MACAddress(mac_address='00:00:00:00:00:02', assigned_object=interfaces[1]),
MACAddress(mac_address='00:00:00:00:00:03', assigned_object=interfaces[2]),
)
MACAddress.objects.bulk_create(mac_addresses)
cls.create_data = [
{
'mac_address': '00:00:00:00:00:04',
'assigned_object_type': 'dcim.interface',
'assigned_object_id': interfaces[3].pk,
},
{
'mac_address': '00:00:00:00:00:05',
'assigned_object_type': 'dcim.interface',
'assigned_object_id': interfaces[4].pk,
},
{
'mac_address': '00:00:00:00:00:06',
},
]

View File

@@ -3470,3 +3470,54 @@ class VirtualDeviceContextTestCase(ViewTestCases.PrimaryObjectViewTestCase):
cls.bulk_edit_data = {
'status': VirtualDeviceContextStatusChoices.STATUS_OFFLINE,
}
class MACAddressTestCase(ViewTestCases.PrimaryObjectViewTestCase):
model = MACAddress
@classmethod
def setUpTestData(cls):
device = create_test_device(name='Device 1')
interfaces = (
Interface(device=device, name='Interface 1', type='1000base-t'),
Interface(device=device, name='Interface 2', type='1000base-t'),
Interface(device=device, name='Interface 3', type='1000base-t'),
Interface(device=device, name='Interface 4', type='1000base-t'),
Interface(device=device, name='Interface 5', type='1000base-t'),
Interface(device=device, name='Interface 6', type='1000base-t'),
)
Interface.objects.bulk_create(interfaces)
mac_addresses = (
MACAddress(mac_address='00:00:00:00:00:01', assigned_object=interfaces[0]),
MACAddress(mac_address='00:00:00:00:00:02', assigned_object=interfaces[1]),
MACAddress(mac_address='00:00:00:00:00:03', assigned_object=interfaces[2]),
)
MACAddress.objects.bulk_create(mac_addresses)
tags = create_tags('Alpha', 'Bravo', 'Charlie')
cls.form_data = {
'mac_address': EUI('00:00:00:00:00:04'),
'description': 'New MAC address',
'interface_id': interfaces[3].pk,
'tags': [t.pk for t in tags],
}
cls.csv_data = (
"mac_address,device,interface",
"00:00:00:00:00:04,Device 1,Interface 4",
"00:00:00:00:00:05,Device 1,Interface 5",
"00:00:00:00:00:06,Device 1,Interface 6",
)
cls.csv_update_data = (
"id,mac_address",
f"{mac_addresses[0].pk},00:00:00:00:00:0a",
f"{mac_addresses[1].pk},00:00:00:00:00:0b",
f"{mac_addresses[2].pk},00:00:00:00:00:0c",
)
cls.bulk_edit_data = {
'description': 'New description',
}

View File

@@ -4,17 +4,15 @@ from django.core.paginator import EmptyPage, PageNotAnInteger
from django.db import transaction
from django.db.models import Prefetch
from django.forms import ModelMultipleChoiceField, MultipleHiddenInput, modelformset_factory
from django.http import HttpResponse
from django.shortcuts import get_object_or_404, redirect, render
from django.urls import reverse
from django.utils.html import escape
from django.utils.safestring import mark_safe
from django.utils.translation import gettext_lazy as _
from django.views.generic import View
from jinja2.exceptions import TemplateError
from circuits.models import Circuit, CircuitTermination
from extras.views import ObjectConfigContextView
from extras.views import ObjectConfigContextView, ObjectRenderConfigView
from ipam.models import ASN, IPAddress, Prefix, VLANGroup
from ipam.tables import InterfaceVLANTable, VLANTranslationRuleTable
from netbox.constants import DEFAULT_ACTION_PERMISSIONS
@@ -424,7 +422,8 @@ class SiteGroupContactsView(ObjectContactsView):
@register_model_view(Site, 'list', path='', detail=False)
class SiteListView(generic.ObjectListView):
queryset = Site.objects.annotate(
device_count=count_related(Device, 'site')
device_count=count_related(Device, 'site'),
asn_count=count_related(ASN, 'sites')
)
filterset = filtersets.SiteFilterSet
filterset_form = forms.SiteFilterForm
@@ -966,6 +965,7 @@ class RackReservationBulkDeleteView(generic.BulkDeleteView):
@register_model_view(Manufacturer, 'list', path='', detail=False)
class ManufacturerListView(generic.ObjectListView):
queryset = Manufacturer.objects.annotate(
racktype_count=count_related(RackType, 'manufacturer'),
devicetype_count=count_related(DeviceType, 'manufacturer'),
moduletype_count=count_related(ModuleType, 'manufacturer'),
inventoryitem_count=count_related(InventoryItem, 'manufacturer'),
@@ -2253,54 +2253,14 @@ class DeviceConfigContextView(ObjectConfigContextView):
@register_model_view(Device, 'render-config')
class DeviceRenderConfigView(generic.ObjectView):
class DeviceRenderConfigView(ObjectRenderConfigView):
queryset = Device.objects.all()
template_name = 'dcim/device/render_config.html'
base_template = 'dcim/device/base.html'
tab = ViewTab(
label=_('Render Config'),
weight=2100
weight=2100,
)
def get(self, request, **kwargs):
instance = self.get_object(**kwargs)
context = self.get_extra_context(request, instance)
# If a direct export has been requested, return the rendered template content as a
# downloadable file.
if request.GET.get('export'):
content = context['rendered_config'] or context['error_message']
response = HttpResponse(content, content_type='text')
filename = f"{instance.name or 'config'}.txt"
response['Content-Disposition'] = f'attachment; filename="{filename}"'
return response
return render(request, self.get_template_name(), {
'object': instance,
'tab': self.tab,
**context,
})
def get_extra_context(self, request, instance):
# Compile context data
context_data = instance.get_config_context()
context_data.update({'device': instance})
# Render the config template
rendered_config = None
error_message = None
if config_template := instance.get_config_template():
try:
rendered_config = config_template.render(context=context_data)
except TemplateError as e:
error_message = _("An error occurred while rendering the template: {error}").format(error=e)
return {
'config_template': config_template,
'context_data': context_data,
'rendered_config': rendered_config,
'error_message': error_message,
}
@register_model_view(Device, 'virtual-machines')
class DeviceVirtualMachinesView(generic.ObjectChildrenView):

View File

@@ -155,7 +155,6 @@ class JournalEntryKindChoices(ChoiceSet):
class LogLevelChoices(ChoiceSet):
LOG_DEBUG = 'debug'
LOG_DEFAULT = 'default'
LOG_INFO = 'info'
LOG_SUCCESS = 'success'
LOG_WARNING = 'warning'
@@ -163,16 +162,15 @@ class LogLevelChoices(ChoiceSet):
CHOICES = (
(LOG_DEBUG, _('Debug'), 'teal'),
(LOG_DEFAULT, _('Default'), 'gray'),
(LOG_INFO, _('Info'), 'cyan'),
(LOG_SUCCESS, _('Success'), 'green'),
(LOG_WARNING, _('Warning'), 'yellow'),
(LOG_FAILURE, _('Failure'), 'red'),
)
SYSTEM_LEVELS = {
LOG_DEBUG: logging.DEBUG,
LOG_DEFAULT: logging.INFO,
LOG_INFO: logging.INFO,
LOG_SUCCESS: logging.INFO,
LOG_WARNING: logging.WARNING,
@@ -180,17 +178,6 @@ class LogLevelChoices(ChoiceSet):
}
class DurationChoices(ChoiceSet):
CHOICES = (
(60, _('Hourly')),
(720, _('12 hours')),
(1440, _('Daily')),
(10080, _('Weekly')),
(43200, _('30 days')),
)
#
# Webhooks
#

View File

@@ -76,7 +76,7 @@ DEFAULT_DASHBOARD = [
'height': 4,
'title': 'NetBox News',
'config': {
'feed_url': 'http://netbox.dev/rss/',
'feed_url': 'https://api.netbox.oss.netboxlabs.com/v1/newsfeed/',
'max_entries': 10,
'cache_timeout': 14400,
'requires_internet': True,
@@ -138,9 +138,8 @@ DEFAULT_DASHBOARD = [
LOG_LEVEL_RANK = {
LogLevelChoices.LOG_DEBUG: 0,
LogLevelChoices.LOG_DEFAULT: 1,
LogLevelChoices.LOG_INFO: 2,
LogLevelChoices.LOG_SUCCESS: 3,
LogLevelChoices.LOG_WARNING: 4,
LogLevelChoices.LOG_FAILURE: 5,
LogLevelChoices.LOG_INFO: 1,
LogLevelChoices.LOG_SUCCESS: 2,
LogLevelChoices.LOG_WARNING: 3,
LogLevelChoices.LOG_FAILURE: 4,
}

View File

@@ -37,6 +37,7 @@ __all__ = (
class CustomFieldFilterForm(SavedFiltersMixin, FilterForm):
model = CustomField
fieldsets = (
FieldSet('q', 'filter_id'),
FieldSet(
@@ -115,6 +116,7 @@ class CustomFieldFilterForm(SavedFiltersMixin, FilterForm):
class CustomFieldChoiceSetFilterForm(SavedFiltersMixin, FilterForm):
model = CustomFieldChoiceSet
fieldsets = (
FieldSet('q', 'filter_id'),
FieldSet('base_choices', 'choice', name=_('Choices')),
@@ -129,6 +131,7 @@ class CustomFieldChoiceSetFilterForm(SavedFiltersMixin, FilterForm):
class CustomLinkFilterForm(SavedFiltersMixin, FilterForm):
model = CustomLink
fieldsets = (
FieldSet('q', 'filter_id'),
FieldSet('object_type', 'enabled', 'new_window', 'weight', name=_('Attributes')),
@@ -159,6 +162,7 @@ class CustomLinkFilterForm(SavedFiltersMixin, FilterForm):
class ExportTemplateFilterForm(SavedFiltersMixin, FilterForm):
model = ExportTemplate
fieldsets = (
FieldSet('q', 'filter_id'),
FieldSet('data_source_id', 'data_file_id', name=_('Data')),
@@ -200,6 +204,7 @@ class ExportTemplateFilterForm(SavedFiltersMixin, FilterForm):
class ImageAttachmentFilterForm(SavedFiltersMixin, FilterForm):
model = ImageAttachment
fieldsets = (
FieldSet('q', 'filter_id'),
FieldSet('object_type_id', 'name', name=_('Attributes')),
@@ -216,6 +221,7 @@ class ImageAttachmentFilterForm(SavedFiltersMixin, FilterForm):
class SavedFilterFilterForm(SavedFiltersMixin, FilterForm):
model = SavedFilter
fieldsets = (
FieldSet('q', 'filter_id'),
FieldSet('object_type', 'enabled', 'shared', 'weight', name=_('Attributes')),
@@ -314,6 +320,7 @@ class TagFilterForm(SavedFiltersMixin, FilterForm):
class ConfigContextFilterForm(SavedFiltersMixin, FilterForm):
model = ConfigContext
fieldsets = (
FieldSet('q', 'filter_id', 'tag_id'),
FieldSet('data_source_id', 'data_file_id', name=_('Data')),
@@ -403,6 +410,7 @@ class ConfigContextFilterForm(SavedFiltersMixin, FilterForm):
class ConfigTemplateFilterForm(SavedFiltersMixin, FilterForm):
model = ConfigTemplate
fieldsets = (
FieldSet('q', 'filter_id', 'tag'),
FieldSet('data_source_id', 'data_file_id', name=_('Data')),
@@ -469,6 +477,7 @@ class JournalEntryFilterForm(NetBoxModelFilterSetForm):
class NotificationGroupFilterForm(SavedFiltersMixin, FilterForm):
model = NotificationGroup
user_id = DynamicModelMultipleChoiceField(
queryset=User.objects.all(),
required=False,

View File

@@ -1,7 +1,7 @@
from django import forms
from django.utils.translation import gettext_lazy as _
from extras.choices import DurationChoices
from core.choices import JobIntervalChoices
from utilities.forms.widgets import DateTimePicker, NumberWithOptions
from utilities.datetime import local_now
@@ -22,7 +22,7 @@ class ReportForm(forms.Form):
min_value=1,
label=_("Recurs every"),
widget=NumberWithOptions(
options=DurationChoices
options=JobIntervalChoices
),
help_text=_("Interval at which this report is re-run (in minutes)")
)

View File

@@ -1,7 +1,7 @@
from django import forms
from django.utils.translation import gettext_lazy as _
from extras.choices import DurationChoices
from core.choices import JobIntervalChoices
from utilities.forms.widgets import DateTimePicker, NumberWithOptions
from utilities.datetime import local_now
@@ -28,7 +28,7 @@ class ScriptForm(forms.Form):
min_value=1,
label=_("Recurs every"),
widget=NumberWithOptions(
options=DurationChoices
options=JobIntervalChoices
),
help_text=_("Interval at which this script is re-run (in minutes)")
)

View File

@@ -81,12 +81,17 @@ class Command(BaseCommand):
logger.error(f'\t{field}: {error.get("message")}')
raise CommandError()
# Remove extra fields from ScriptForm before passng data to script
form.cleaned_data.pop('_schedule_at')
form.cleaned_data.pop('_interval')
form.cleaned_data.pop('_commit')
# Execute the script.
job = ScriptJob.enqueue(
instance=script_obj,
user=user,
immediate=True,
data=data,
data=form.cleaned_data,
request=NetBoxFakeRequest({
'META': {},
'POST': data,

View File

@@ -120,11 +120,12 @@ class ConfigContextModelQuerySet(RestrictedQuerySet):
is_active=True,
)
# Apply Location & DeviceType filters only for VirtualMachines
if self.model._meta.model_name == 'device':
base_query.add((Q(locations=OuterRef('location')) | Q(locations=None)), Q.AND)
base_query.add((Q(device_types=OuterRef('device_type')) | Q(device_types=None)), Q.AND)
elif self.model._meta.model_name == 'virtualmachine':
base_query.add(Q(locations=None), Q.AND)
base_query.add(Q(device_types=None), Q.AND)
base_query.add((Q(roles=OuterRef('role')) | Q(roles=None)), Q.AND)

View File

@@ -15,7 +15,7 @@ class Report(BaseScript):
# There is no generic log() equivalent on BaseScript
def log(self, message):
self._log(message, None, level=LogLevelChoices.LOG_DEFAULT)
self._log(message, None, level=LogLevelChoices.LOG_INFO)
def log_success(self, obj=None, message=None):
super().log_success(message, obj)

View File

@@ -460,7 +460,7 @@ class BaseScript:
# Logging
#
def _log(self, message, obj=None, level=LogLevelChoices.LOG_DEFAULT):
def _log(self, message, obj=None, level=LogLevelChoices.LOG_INFO):
"""
Log a message. Do not call this method directly; use one of the log_* wrappers below.
"""

View File

@@ -660,8 +660,8 @@ class CustomFieldAPITest(APITestCase):
CustomField(
type=CustomFieldTypeChoices.TYPE_BOOLEAN,
name='boolean_field',
default=False)
,
default=False
),
CustomField(
type=CustomFieldTypeChoices.TYPE_DATE,
name='date_field',

View File

@@ -1118,6 +1118,7 @@ class TagTestCase(TestCase, ChangeLoggedFilterSetTests):
'devicerole',
'devicetype',
'dummymodel', # From dummy_plugin
'dummynetboxmodel', # From dummy_plugin
'eventrule',
'fhrpgroup',
'frontport',

View File

@@ -10,6 +10,7 @@ from django.utils import timezone
from django.utils.module_loading import import_string
from django.utils.translation import gettext as _
from django.views.generic import View
from jinja2.exceptions import TemplateError
from core.choices import ManagedFileRootPathChoices
from core.forms import ManagedFileForm
@@ -885,6 +886,61 @@ class ConfigTemplateBulkSyncDataView(generic.BulkSyncDataView):
queryset = ConfigTemplate.objects.all()
class ObjectRenderConfigView(generic.ObjectView):
base_template = None
template_name = 'extras/object_render_config.html'
def get(self, request, **kwargs):
instance = self.get_object(**kwargs)
context = self.get_extra_context(request, instance)
# If a direct export has been requested, return the rendered template content as a
# downloadable file.
if request.GET.get('export'):
content = context['rendered_config'] or context['error_message']
response = HttpResponse(content, content_type='text')
filename = f"{instance.name or 'config'}.txt"
response['Content-Disposition'] = f'attachment; filename="{filename}"'
return response
return render(
request,
self.get_template_name(),
{
'object': instance,
'tab': self.tab,
**context,
},
)
def get_extra_context_data(self, request, instance):
return {
f'{instance._meta.model_name}': instance,
}
def get_extra_context(self, request, instance):
# Compile context data
context_data = instance.get_config_context()
context_data.update(self.get_extra_context_data(request, instance))
# Render the config template
rendered_config = None
error_message = None
if config_template := instance.get_config_template():
try:
rendered_config = config_template.render(context=context_data)
except TemplateError as e:
error_message = _("An error occurred while rendering the template: {error}").format(error=e)
return {
'base_template': self.base_template,
'config_template': config_template,
'context_data': context_data,
'rendered_config': rendered_config,
'error_message': error_message,
}
#
# Image attachments
#
@@ -1315,9 +1371,9 @@ class ScriptResultView(TableMixin, generic.ObjectView):
index = 0
try:
log_threshold = LOG_LEVEL_RANK[request.GET.get('log_threshold', LogLevelChoices.LOG_DEBUG)]
log_threshold = LOG_LEVEL_RANK[request.GET.get('log_threshold', LogLevelChoices.LOG_INFO)]
except KeyError:
log_threshold = LOG_LEVEL_RANK[LogLevelChoices.LOG_DEBUG]
log_threshold = LOG_LEVEL_RANK[LogLevelChoices.LOG_INFO]
if job.data:
if 'log' in job.data:
@@ -1325,7 +1381,7 @@ class ScriptResultView(TableMixin, generic.ObjectView):
tests = job.data['tests']
for log in job.data['log']:
log_level = LOG_LEVEL_RANK.get(log.get('status'), LogLevelChoices.LOG_DEFAULT)
log_level = LOG_LEVEL_RANK.get(log.get('status'), LogLevelChoices.LOG_INFO)
if log_level >= log_threshold:
index += 1
result = {
@@ -1348,7 +1404,7 @@ class ScriptResultView(TableMixin, generic.ObjectView):
for method, test_data in tests.items():
if 'log' in test_data:
for time, status, obj, url, message in test_data['log']:
log_level = LOG_LEVEL_RANK.get(status, LogLevelChoices.LOG_DEFAULT)
log_level = LOG_LEVEL_RANK.get(status, LogLevelChoices.LOG_INFO)
if log_level >= log_threshold:
index += 1
result = {
@@ -1374,9 +1430,9 @@ class ScriptResultView(TableMixin, generic.ObjectView):
if job.completed:
table = self.get_table(job, request, bulk_actions=False)
log_threshold = request.GET.get('log_threshold', LogLevelChoices.LOG_DEBUG)
log_threshold = request.GET.get('log_threshold', LogLevelChoices.LOG_INFO)
if log_threshold not in LOG_LEVEL_RANK:
log_threshold = LogLevelChoices.LOG_DEBUG
log_threshold = LogLevelChoices.LOG_INFO
context = {
'script': job.object,

View File

@@ -15,7 +15,7 @@ def populate_denormalized_fields(apps, schema_editor):
prefix._site_id = prefix.site_id
# Note: Location cannot be set prior to migration
Prefix.objects.bulk_update(prefixes, ['_region', '_site_group', '_site'])
Prefix.objects.bulk_update(prefixes, ['_region', '_site_group', '_site'], batch_size=100)
class Migration(migrations.Migration):

View File

@@ -361,7 +361,7 @@ class VLANTranslationRule(NetBoxModel):
)
local_vid = models.PositiveSmallIntegerField(
verbose_name=_('Local VLAN ID'),
validators=(
validators=(
MinValueValidator(VLAN_VID_MIN),
MaxValueValidator(VLAN_VID_MAX)
),
@@ -369,7 +369,7 @@ class VLANTranslationRule(NetBoxModel):
)
remote_vid = models.PositiveSmallIntegerField(
verbose_name=_('Remote VLAN ID'),
validators=(
validators=(
MinValueValidator(VLAN_VID_MIN),
MaxValueValidator(VLAN_VID_MAX)
),

View File

@@ -192,7 +192,8 @@ class PrefixTable(TenancyColumnsMixin, NetBoxTable):
)
scope = tables.Column(
verbose_name=_('Scope'),
linkify=True
linkify=True,
orderable=False
)
vlan_group = tables.Column(
accessor='vlan__group',

View File

@@ -863,6 +863,13 @@ class IPAddressEditView(generic.ObjectEditView):
return obj
def get_extra_addanother_params(self, request):
if 'interface' in request.GET:
return {'interface': request.GET['interface']}
elif 'vminterface' in request.GET:
return {'vminterface': request.GET['vminterface']}
return {}
# TODO: Standardize or remove this view
@register_model_view(IPAddress, 'assign', path='assign', detail=False)

View File

@@ -169,15 +169,6 @@ class NetBoxModelFilterSetForm(CustomFieldsMixin, SavedFiltersMixin, forms.Form)
selector_fields = ('filter_id', 'q')
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# Limit saved filters to those applicable to the form's model
object_type = ObjectType.objects.get_for_model(self.model)
self.fields['filter_id'].widget.add_query_params({
'object_type_id': object_type.pk,
})
def _get_custom_fields(self, content_type):
return super()._get_custom_fields(content_type).exclude(
Q(filter_logic=CustomFieldFilterLogicChoices.FILTER_DISABLED) |

View File

@@ -73,6 +73,16 @@ class SavedFiltersMixin(forms.Form):
}
)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# Limit saved filters to those applicable to the form's model
if hasattr(self, 'model'):
object_type = ObjectType.objects.get_for_model(self.model)
self.fields['filter_id'].widget.add_query_params({
'object_type_id': object_type.pk,
})
class TagsMixin(forms.Form):
tags = DynamicModelMultipleChoiceField(

View File

@@ -10,6 +10,7 @@ from mptt.models import MPTTModel, TreeForeignKey
from netbox.models.features import *
from utilities.mptt import TreeManager
from utilities.querysets import RestrictedQuerySet
from utilities.views import get_viewname
__all__ = (
@@ -42,7 +43,7 @@ class NetBoxFeatureSet(
return f'{settings.STATIC_URL}docs/models/{self._meta.app_label}/{self._meta.model_name}/'
def get_absolute_url(self):
return reverse(f'{self._meta.app_label}:{self._meta.model_name}', args=[self.pk])
return reverse(get_viewname(self), args=[self.pk])
#

View File

@@ -38,9 +38,10 @@ class PluginMenuItem:
permissions = []
buttons = []
def __init__(self, link, link_text, staff_only=False, permissions=None, buttons=None):
def __init__(self, link, link_text, auth_required=False, staff_only=False, permissions=None, buttons=None):
self.link = link
self.link_text = link_text
self.auth_required = auth_required
self.staff_only = staff_only
if permissions is not None:
if type(permissions) not in (list, tuple):

View File

@@ -5,9 +5,7 @@ import os
import platform
import sys
import warnings
from urllib.parse import urlencode
import requests
from django.contrib.messages import constants as messages
from django.core.exceptions import ImproperlyConfigured, ValidationError
from django.core.validators import URLValidator
@@ -224,8 +222,18 @@ DATABASES = {
# Storage backend
#
# Default STORAGES for Django
STORAGES = {
"default": {
"BACKEND": "django.core.files.storage.FileSystemStorage",
},
"staticfiles": {
"BACKEND": "django.contrib.staticfiles.storage.StaticFilesStorage",
},
}
if STORAGE_BACKEND is not None:
DEFAULT_FILE_STORAGE = STORAGE_BACKEND
STORAGES['default']['BACKEND'] = STORAGE_BACKEND
# django-storages
if STORAGE_BACKEND.startswith('storages.'):
@@ -583,17 +591,6 @@ if SENTRY_ENABLED:
# Calculate a unique deployment ID from the secret key
DEPLOYMENT_ID = hashlib.sha256(SECRET_KEY.encode('utf-8')).hexdigest()[:16]
CENSUS_URL = 'https://census.netbox.oss.netboxlabs.com/api/v1/'
CENSUS_PARAMS = {
'version': RELEASE.full_version,
'python_version': sys.version.split()[0],
'deployment_id': DEPLOYMENT_ID,
}
if CENSUS_REPORTING_ENABLED and not ISOLATED_DEPLOYMENT and not DEBUG and 'test' not in sys.argv:
try:
# Report anonymous census data
requests.get(f'{CENSUS_URL}?{urlencode(CENSUS_PARAMS)}', timeout=3, proxies=HTTP_PROXIES)
except requests.exceptions.RequestException:
pass
#

View File

@@ -2,6 +2,7 @@ from copy import deepcopy
from functools import cached_property
import django_tables2 as tables
from django.conf import settings
from django.contrib.auth.models import AnonymousUser
from django.contrib.contenttypes.fields import GenericForeignKey
from django.core.exceptions import FieldDoesNotExist
@@ -64,6 +65,8 @@ class BaseTable(tables.Table):
selected_columns = None
if user is not None and not isinstance(user, AnonymousUser):
selected_columns = user.config.get(f"tables.{self.name}.columns")
elif isinstance(user, AnonymousUser) and hasattr(settings, 'DEFAULT_USER_PREFERENCES'):
selected_columns = settings.DEFAULT_USER_PREFERENCES.get('tables', {}).get(self.name, {}).get('columns')
if not selected_columns:
selected_columns = getattr(self.Meta, 'default_columns', self.Meta.fields)

View File

@@ -0,0 +1,30 @@
import taggit.managers
import utilities.json
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('dummy_plugin', '0001_initial'),
('extras', '0122_charfield_null_choices'),
]
operations = [
migrations.CreateModel(
name='DummyNetBoxModel',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)),
('created', models.DateTimeField(auto_now_add=True, null=True)),
('last_updated', models.DateTimeField(auto_now=True, null=True)),
(
'custom_field_data',
models.JSONField(blank=True, default=dict, encoder=utilities.json.CustomFieldJSONEncoder),
),
('tags', taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag')),
],
options={
'abstract': False,
},
),
]

View File

@@ -1,5 +1,7 @@
from django.db import models
from netbox.models import NetBoxModel
class DummyModel(models.Model):
name = models.CharField(
@@ -11,3 +13,7 @@ class DummyModel(models.Model):
class Meta:
ordering = ['name']
class DummyNetBoxModel(NetBoxModel):
pass

View File

@@ -6,4 +6,6 @@ from . import views
urlpatterns = (
path('models/', views.DummyModelsView.as_view(), name='dummy_model_list'),
path('models/add/', views.DummyModelAddView.as_view(), name='dummy_model_add'),
path('netboxmodel/<int:pk>/', views.DummyNetBoxModelView.as_view(), name='dummynetboxmodel'),
)

View File

@@ -5,12 +5,17 @@ from django.http import HttpResponse
from django.views.generic import View
from dcim.models import Site
from netbox.views import generic
from utilities.views import register_model_view
from .models import DummyModel
from .models import DummyModel, DummyNetBoxModel
# Trigger registration of custom column
from .tables import mycol # noqa: F401
#
# DummyModel
#
class DummyModelsView(View):
def get(self, request):
@@ -32,6 +37,18 @@ class DummyModelAddView(View):
return HttpResponse("Instance created")
#
# DummyNetBoxModel
#
class DummyNetBoxModelView(generic.ObjectView):
queryset = DummyNetBoxModel.objects.all()
#
# API
#
@register_model_view(Site, 'extra', path='other-stuff')
class ExtraCoreModelView(View):

View File

@@ -0,0 +1,23 @@
from unittest import skipIf
from django.conf import settings
from django.test import TestCase
from core.models import ObjectChange
from netbox.tests.dummy_plugin.models import DummyNetBoxModel
class ModelTest(TestCase):
def test_get_absolute_url(self):
m = ObjectChange()
m.pk = 123
self.assertEqual(m.get_absolute_url(), f'/core/changelog/{m.pk}/')
@skipIf('netbox.tests.dummy_plugin' not in settings.PLUGINS, "dummy_plugin not in settings.PLUGINS")
def test_get_absolute_url_plugin(self):
m = DummyNetBoxModel()
m.pk = 123
self.assertEqual(m.get_absolute_url(), f'/plugins/dummy-plugin/netboxmodel/{m.pk}/')

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -27,11 +27,11 @@
"bootstrap": "5.3.3",
"clipboard": "2.0.11",
"flatpickr": "4.6.13",
"gridstack": "11.2.0",
"gridstack": "11.3.0",
"htmx.org": "1.9.12",
"query-string": "9.1.1",
"sass": "1.83.1",
"tom-select": "2.4.1",
"sass": "1.85.0",
"tom-select": "2.4.3",
"typeface-inter": "3.18.1",
"typeface-roboto-mono": "1.1.13"
},
@@ -41,7 +41,7 @@
"@types/node": "^22.3.0",
"@typescript-eslint/eslint-plugin": "^8.1.0",
"@typescript-eslint/parser": "^8.1.0",
"esbuild": "^0.23.1",
"esbuild": "^0.24.2",
"esbuild-sass-plugin": "^3.3.1",
"eslint": "<9.0",
"eslint-config-prettier": "^9.1.0",
@@ -53,5 +53,6 @@
},
"resolutions": {
"@types/bootstrap/**/@popperjs/core": "^2.11.6"
}
},
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
}

View File

@@ -43,7 +43,9 @@ function toggleCheckboxRange(
const typedElement = element as HTMLInputElement;
//Change loop's current checkbox state to eventTargetElement checkbox state
if (changePkCheckboxState === true) {
typedElement.checked = eventTargetElement.checked;
if (!typedElement.closest('tr')?.classList.contains('d-none')) {
typedElement.checked = eventTargetElement.checked;
}
}
//The previously clicked checkbox was above the shift clicked checkbox
if (element === previousStateElement) {
@@ -52,7 +54,9 @@ function toggleCheckboxRange(
return;
}
changePkCheckboxState = true;
typedElement.checked = eventTargetElement.checked;
if (!typedElement.closest('tr')?.classList.contains('d-none')) {
typedElement.checked = eventTargetElement.checked;
}
}
//The previously clicked checkbox was below the shift clicked checkbox
if (element === eventTargetElement) {

View File

@@ -1,5 +1,6 @@
import { initForms } from './forms';
import { initButtons } from './buttons';
import { initClipboard } from './clipboard'
import { initClipboard } from './clipboard';
import { initSelects } from './select';
import { initObjectSelector } from './objectSelector';
import { initBootstrap } from './bs';
@@ -9,6 +10,7 @@ import { initQuickAdd } from './quickAdd';
function initDepedencies(): void {
initButtons();
initClipboard();
initForms();
initSelects();
initObjectSelector();
initQuickAdd();

View File

@@ -21,125 +21,130 @@
resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.4.tgz#19bf0f5af19149111c40d98bb0cf82119f5d9eeb"
integrity sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==
"@esbuild/aix-ppc64@0.23.1":
version "0.23.1"
resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.23.1.tgz#51299374de171dbd80bb7d838e1cfce9af36f353"
integrity sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ==
"@esbuild/aix-ppc64@0.24.2":
version "0.24.2"
resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.24.2.tgz#38848d3e25afe842a7943643cbcd387cc6e13461"
integrity sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==
"@esbuild/android-arm64@0.23.1":
version "0.23.1"
resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.23.1.tgz#58565291a1fe548638adb9c584237449e5e14018"
integrity sha512-xw50ipykXcLstLeWH7WRdQuysJqejuAGPd30vd1i5zSyKK3WE+ijzHmLKxdiCMtH1pHz78rOg0BKSYOSB/2Khw==
"@esbuild/android-arm64@0.24.2":
version "0.24.2"
resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.24.2.tgz#f592957ae8b5643129fa889c79e69cd8669bb894"
integrity sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg==
"@esbuild/android-arm@0.23.1":
version "0.23.1"
resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.23.1.tgz#5eb8c652d4c82a2421e3395b808e6d9c42c862ee"
integrity sha512-uz6/tEy2IFm9RYOyvKl88zdzZfwEfKZmnX9Cj1BHjeSGNuGLuMD1kR8y5bteYmwqKm1tj8m4cb/aKEorr6fHWQ==
"@esbuild/android-arm@0.24.2":
version "0.24.2"
resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.24.2.tgz#72d8a2063aa630308af486a7e5cbcd1e134335b3"
integrity sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q==
"@esbuild/android-x64@0.23.1":
version "0.23.1"
resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.23.1.tgz#ae19d665d2f06f0f48a6ac9a224b3f672e65d517"
integrity sha512-nlN9B69St9BwUoB+jkyU090bru8L0NA3yFvAd7k8dNsVH8bi9a8cUAUSEcEEgTp2z3dbEDGJGfP6VUnkQnlReg==
"@esbuild/android-x64@0.24.2":
version "0.24.2"
resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.24.2.tgz#9a7713504d5f04792f33be9c197a882b2d88febb"
integrity sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw==
"@esbuild/darwin-arm64@0.23.1":
version "0.23.1"
resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.23.1.tgz#05b17f91a87e557b468a9c75e9d85ab10c121b16"
integrity sha512-YsS2e3Wtgnw7Wq53XXBLcV6JhRsEq8hkfg91ESVadIrzr9wO6jJDMZnCQbHm1Guc5t/CdDiFSSfWP58FNuvT3Q==
"@esbuild/darwin-arm64@0.24.2":
version "0.24.2"
resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.24.2.tgz#02ae04ad8ebffd6e2ea096181b3366816b2b5936"
integrity sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA==
"@esbuild/darwin-x64@0.23.1":
version "0.23.1"
resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.23.1.tgz#c58353b982f4e04f0d022284b8ba2733f5ff0931"
integrity sha512-aClqdgTDVPSEGgoCS8QDG37Gu8yc9lTHNAQlsztQ6ENetKEO//b8y31MMu2ZaPbn4kVsIABzVLXYLhCGekGDqw==
"@esbuild/darwin-x64@0.24.2":
version "0.24.2"
resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.24.2.tgz#9ec312bc29c60e1b6cecadc82bd504d8adaa19e9"
integrity sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA==
"@esbuild/freebsd-arm64@0.23.1":
version "0.23.1"
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.23.1.tgz#f9220dc65f80f03635e1ef96cfad5da1f446f3bc"
integrity sha512-h1k6yS8/pN/NHlMl5+v4XPfikhJulk4G+tKGFIOwURBSFzE8bixw1ebjluLOjfwtLqY0kewfjLSrO6tN2MgIhA==
"@esbuild/freebsd-arm64@0.24.2":
version "0.24.2"
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.2.tgz#5e82f44cb4906d6aebf24497d6a068cfc152fa00"
integrity sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg==
"@esbuild/freebsd-x64@0.23.1":
version "0.23.1"
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.23.1.tgz#69bd8511fa013b59f0226d1609ac43f7ce489730"
integrity sha512-lK1eJeyk1ZX8UklqFd/3A60UuZ/6UVfGT2LuGo3Wp4/z7eRTRYY+0xOu2kpClP+vMTi9wKOfXi2vjUpO1Ro76g==
"@esbuild/freebsd-x64@0.24.2":
version "0.24.2"
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.24.2.tgz#3fb1ce92f276168b75074b4e51aa0d8141ecce7f"
integrity sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q==
"@esbuild/linux-arm64@0.23.1":
version "0.23.1"
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.23.1.tgz#8050af6d51ddb388c75653ef9871f5ccd8f12383"
integrity sha512-/93bf2yxencYDnItMYV/v116zff6UyTjo4EtEQjUBeGiVpMmffDNUyD9UN2zV+V3LRV3/on4xdZ26NKzn6754g==
"@esbuild/linux-arm64@0.24.2":
version "0.24.2"
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.24.2.tgz#856b632d79eb80aec0864381efd29de8fd0b1f43"
integrity sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg==
"@esbuild/linux-arm@0.23.1":
version "0.23.1"
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.23.1.tgz#ecaabd1c23b701070484990db9a82f382f99e771"
integrity sha512-CXXkzgn+dXAPs3WBwE+Kvnrf4WECwBdfjfeYHpMeVxWE0EceB6vhWGShs6wi0IYEqMSIzdOF1XjQ/Mkm5d7ZdQ==
"@esbuild/linux-arm@0.24.2":
version "0.24.2"
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.24.2.tgz#c846b4694dc5a75d1444f52257ccc5659021b736"
integrity sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA==
"@esbuild/linux-ia32@0.23.1":
version "0.23.1"
resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.23.1.tgz#3ed2273214178109741c09bd0687098a0243b333"
integrity sha512-VTN4EuOHwXEkXzX5nTvVY4s7E/Krz7COC8xkftbbKRYAl96vPiUssGkeMELQMOnLOJ8k3BY1+ZY52tttZnHcXQ==
"@esbuild/linux-ia32@0.24.2":
version "0.24.2"
resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.24.2.tgz#f8a16615a78826ccbb6566fab9a9606cfd4a37d5"
integrity sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw==
"@esbuild/linux-loong64@0.23.1":
version "0.23.1"
resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.23.1.tgz#a0fdf440b5485c81b0fbb316b08933d217f5d3ac"
integrity sha512-Vx09LzEoBa5zDnieH8LSMRToj7ir/Jeq0Gu6qJ/1GcBq9GkfoEAoXvLiW1U9J1qE/Y/Oyaq33w5p2ZWrNNHNEw==
"@esbuild/linux-loong64@0.24.2":
version "0.24.2"
resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.24.2.tgz#1c451538c765bf14913512c76ed8a351e18b09fc"
integrity sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ==
"@esbuild/linux-mips64el@0.23.1":
version "0.23.1"
resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.23.1.tgz#e11a2806346db8375b18f5e104c5a9d4e81807f6"
integrity sha512-nrFzzMQ7W4WRLNUOU5dlWAqa6yVeI0P78WKGUo7lg2HShq/yx+UYkeNSE0SSfSure0SqgnsxPvmAUu/vu0E+3Q==
"@esbuild/linux-mips64el@0.24.2":
version "0.24.2"
resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.24.2.tgz#0846edeefbc3d8d50645c51869cc64401d9239cb"
integrity sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw==
"@esbuild/linux-ppc64@0.23.1":
version "0.23.1"
resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.23.1.tgz#06a2744c5eaf562b1a90937855b4d6cf7c75ec96"
integrity sha512-dKN8fgVqd0vUIjxuJI6P/9SSSe/mB9rvA98CSH2sJnlZ/OCZWO1DJvxj8jvKTfYUdGfcq2dDxoKaC6bHuTlgcw==
"@esbuild/linux-ppc64@0.24.2":
version "0.24.2"
resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.24.2.tgz#8e3fc54505671d193337a36dfd4c1a23b8a41412"
integrity sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw==
"@esbuild/linux-riscv64@0.23.1":
version "0.23.1"
resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.23.1.tgz#65b46a2892fc0d1af4ba342af3fe0fa4a8fe08e7"
integrity sha512-5AV4Pzp80fhHL83JM6LoA6pTQVWgB1HovMBsLQ9OZWLDqVY8MVobBXNSmAJi//Csh6tcY7e7Lny2Hg1tElMjIA==
"@esbuild/linux-riscv64@0.24.2":
version "0.24.2"
resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.24.2.tgz#6a1e92096d5e68f7bb10a0d64bb5b6d1daf9a694"
integrity sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q==
"@esbuild/linux-s390x@0.23.1":
version "0.23.1"
resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.23.1.tgz#e71ea18c70c3f604e241d16e4e5ab193a9785d6f"
integrity sha512-9ygs73tuFCe6f6m/Tb+9LtYxWR4c9yg7zjt2cYkjDbDpV/xVn+68cQxMXCjUpYwEkze2RcU/rMnfIXNRFmSoDw==
"@esbuild/linux-s390x@0.24.2":
version "0.24.2"
resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.24.2.tgz#ab18e56e66f7a3c49cb97d337cd0a6fea28a8577"
integrity sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw==
"@esbuild/linux-x64@0.23.1":
version "0.23.1"
resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.23.1.tgz#d47f97391e80690d4dfe811a2e7d6927ad9eed24"
integrity sha512-EV6+ovTsEXCPAp58g2dD68LxoP/wK5pRvgy0J/HxPGB009omFPv3Yet0HiaqvrIrgPTBuC6wCH1LTOY91EO5hQ==
"@esbuild/linux-x64@0.24.2":
version "0.24.2"
resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.24.2.tgz#8140c9b40da634d380b0b29c837a0b4267aff38f"
integrity sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q==
"@esbuild/netbsd-x64@0.23.1":
version "0.23.1"
resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.23.1.tgz#44e743c9778d57a8ace4b72f3c6b839a3b74a653"
integrity sha512-aevEkCNu7KlPRpYLjwmdcuNz6bDFiE7Z8XC4CPqExjTvrHugh28QzUXVOZtiYghciKUacNktqxdpymplil1beA==
"@esbuild/netbsd-arm64@0.24.2":
version "0.24.2"
resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.24.2.tgz#65f19161432bafb3981f5f20a7ff45abb2e708e6"
integrity sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw==
"@esbuild/openbsd-arm64@0.23.1":
version "0.23.1"
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.23.1.tgz#05c5a1faf67b9881834758c69f3e51b7dee015d7"
integrity sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q==
"@esbuild/netbsd-x64@0.24.2":
version "0.24.2"
resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.24.2.tgz#7a3a97d77abfd11765a72f1c6f9b18f5396bcc40"
integrity sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw==
"@esbuild/openbsd-x64@0.23.1":
version "0.23.1"
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.23.1.tgz#2e58ae511bacf67d19f9f2dcd9e8c5a93f00c273"
integrity sha512-aY2gMmKmPhxfU+0EdnN+XNtGbjfQgwZj43k8G3fyrDM/UdZww6xrWxmDkuz2eCZchqVeABjV5BpildOrUbBTqA==
"@esbuild/openbsd-arm64@0.24.2":
version "0.24.2"
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.2.tgz#58b00238dd8f123bfff68d3acc53a6ee369af89f"
integrity sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A==
"@esbuild/sunos-x64@0.23.1":
version "0.23.1"
resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.23.1.tgz#adb022b959d18d3389ac70769cef5a03d3abd403"
integrity sha512-RBRT2gqEl0IKQABT4XTj78tpk9v7ehp+mazn2HbUeZl1YMdaGAQqhapjGTCe7uw7y0frDi4gS0uHzhvpFuI1sA==
"@esbuild/openbsd-x64@0.24.2":
version "0.24.2"
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.24.2.tgz#0ac843fda0feb85a93e288842936c21a00a8a205"
integrity sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA==
"@esbuild/win32-arm64@0.23.1":
version "0.23.1"
resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.23.1.tgz#84906f50c212b72ec360f48461d43202f4c8b9a2"
integrity sha512-4O+gPR5rEBe2FpKOVyiJ7wNDPA8nGzDuJ6gN4okSA1gEOYZ67N8JPk58tkWtdtPeLz7lBnY6I5L3jdsr3S+A6A==
"@esbuild/sunos-x64@0.24.2":
version "0.24.2"
resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.24.2.tgz#8b7aa895e07828d36c422a4404cc2ecf27fb15c6"
integrity sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig==
"@esbuild/win32-ia32@0.23.1":
version "0.23.1"
resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.23.1.tgz#5e3eacc515820ff729e90d0cb463183128e82fac"
integrity sha512-BcaL0Vn6QwCwre3Y717nVHZbAa4UBEigzFm6VdsVdT/MbZ38xoj1X9HPkZhbmaBGUD1W8vxAfffbDe8bA6AKnQ==
"@esbuild/win32-arm64@0.24.2":
version "0.24.2"
resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.24.2.tgz#c023afb647cabf0c3ed13f0eddfc4f1d61c66a85"
integrity sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ==
"@esbuild/win32-x64@0.23.1":
version "0.23.1"
resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.23.1.tgz#81fd50d11e2c32b2d6241470e3185b70c7b30699"
integrity sha512-BHpFFeslkWrXWyUPnbKm+xYYVYruCinGcftSBaa8zoF9hZO4BcSCFUvHVTtzpIY6YzUnYtuEhZ+C9iEXjxnasg==
"@esbuild/win32-ia32@0.24.2":
version "0.24.2"
resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.24.2.tgz#96c356132d2dda990098c8b8b951209c3cd743c2"
integrity sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA==
"@esbuild/win32-x64@0.24.2":
version "0.24.2"
resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.24.2.tgz#34aa0b52d0fbb1a654b596acfa595f0c7b77a77b"
integrity sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg==
"@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0":
version "4.4.0"
@@ -1429,35 +1434,36 @@ esbuild-sass-plugin@^3.3.1:
safe-identifier "^0.4.2"
sass "^1.71.1"
esbuild@^0.23.1:
version "0.23.1"
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.23.1.tgz#40fdc3f9265ec0beae6f59824ade1bd3d3d2dab8"
integrity sha512-VVNz/9Sa0bs5SELtn3f7qhJCDPCF5oMEl5cO9/SSinpE9hbPVvxbd572HH5AKiP7WD8INO53GgfDDhRjkylHEg==
esbuild@^0.24.2:
version "0.24.2"
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.24.2.tgz#b5b55bee7de017bff5fb8a4e3e44f2ebe2c3567d"
integrity sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA==
optionalDependencies:
"@esbuild/aix-ppc64" "0.23.1"
"@esbuild/android-arm" "0.23.1"
"@esbuild/android-arm64" "0.23.1"
"@esbuild/android-x64" "0.23.1"
"@esbuild/darwin-arm64" "0.23.1"
"@esbuild/darwin-x64" "0.23.1"
"@esbuild/freebsd-arm64" "0.23.1"
"@esbuild/freebsd-x64" "0.23.1"
"@esbuild/linux-arm" "0.23.1"
"@esbuild/linux-arm64" "0.23.1"
"@esbuild/linux-ia32" "0.23.1"
"@esbuild/linux-loong64" "0.23.1"
"@esbuild/linux-mips64el" "0.23.1"
"@esbuild/linux-ppc64" "0.23.1"
"@esbuild/linux-riscv64" "0.23.1"
"@esbuild/linux-s390x" "0.23.1"
"@esbuild/linux-x64" "0.23.1"
"@esbuild/netbsd-x64" "0.23.1"
"@esbuild/openbsd-arm64" "0.23.1"
"@esbuild/openbsd-x64" "0.23.1"
"@esbuild/sunos-x64" "0.23.1"
"@esbuild/win32-arm64" "0.23.1"
"@esbuild/win32-ia32" "0.23.1"
"@esbuild/win32-x64" "0.23.1"
"@esbuild/aix-ppc64" "0.24.2"
"@esbuild/android-arm" "0.24.2"
"@esbuild/android-arm64" "0.24.2"
"@esbuild/android-x64" "0.24.2"
"@esbuild/darwin-arm64" "0.24.2"
"@esbuild/darwin-x64" "0.24.2"
"@esbuild/freebsd-arm64" "0.24.2"
"@esbuild/freebsd-x64" "0.24.2"
"@esbuild/linux-arm" "0.24.2"
"@esbuild/linux-arm64" "0.24.2"
"@esbuild/linux-ia32" "0.24.2"
"@esbuild/linux-loong64" "0.24.2"
"@esbuild/linux-mips64el" "0.24.2"
"@esbuild/linux-ppc64" "0.24.2"
"@esbuild/linux-riscv64" "0.24.2"
"@esbuild/linux-s390x" "0.24.2"
"@esbuild/linux-x64" "0.24.2"
"@esbuild/netbsd-arm64" "0.24.2"
"@esbuild/netbsd-x64" "0.24.2"
"@esbuild/openbsd-arm64" "0.24.2"
"@esbuild/openbsd-x64" "0.24.2"
"@esbuild/sunos-x64" "0.24.2"
"@esbuild/win32-arm64" "0.24.2"
"@esbuild/win32-ia32" "0.24.2"
"@esbuild/win32-x64" "0.24.2"
escape-string-regexp@^4.0.0:
version "4.0.0"
@@ -1905,10 +1911,10 @@ graphql@16.10.0:
resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.10.0.tgz#24c01ae0af6b11ea87bf55694429198aaa8e220c"
integrity sha512-AjqGKbDGUFRKIRCP9tCKiIGHyriz2oHEbPIbEtcSLSs4YjReZOIPQQWek4+6hjw62H9QShXHyaGivGiYVLeYFQ==
gridstack@11.2.0:
version "11.2.0"
resolved "https://registry.yarnpkg.com/gridstack/-/gridstack-11.2.0.tgz#8977a6632c521260f064ef171b92c7a8df4f58a9"
integrity sha512-ajwUzd9spR8NXDxfJotHWq9WOYoDOV9o6UJR3ksevNz8cvXNxDtI9H/lC+RN6ijM2DexureLlsG0RpYjBZiOtg==
gridstack@11.3.0:
version "11.3.0"
resolved "https://registry.yarnpkg.com/gridstack/-/gridstack-11.3.0.tgz#b110c66bafc64c920fc54933e2c9df4f7b2cfffe"
integrity sha512-Z0eRovKcZTRTs3zetJwjO6CNwrgIy845WfOeZGk8ybpeMCE8fMA8tScyKU72Y2M6uGHkjgwnjflglvPiv+RcBQ==
has-bigints@^1.0.1, has-bigints@^1.0.2:
version "1.0.2"
@@ -2667,10 +2673,10 @@ safe-regex-test@^1.0.3:
es-errors "^1.3.0"
is-regex "^1.1.4"
sass@1.83.1:
version "1.83.1"
resolved "https://registry.yarnpkg.com/sass/-/sass-1.83.1.tgz#dee1ab94b47a6f9993d3195d36f556bcbda64846"
integrity sha512-EVJbDaEs4Rr3F0glJzFSOvtg2/oy2V/YrGFPqPY24UqcLDWcI9ZY5sN+qyO3c/QCZwzgfirvhXvINiJCE/OLcA==
sass@1.83.4:
version "1.83.4"
resolved "https://registry.yarnpkg.com/sass/-/sass-1.83.4.tgz#5ccf60f43eb61eeec300b780b8dcb85f16eec6d1"
integrity sha512-B1bozCeNQiOgDcLd33e2Cs2U60wZwjUUXzh900ZyQF5qUasvMdDZYbQ566LJu7cqR+sAHlAfO6RMkaID5s6qpA==
dependencies:
chokidar "^4.0.0"
immutable "^5.0.2"
@@ -2876,10 +2882,10 @@ toggle-selection@^1.0.6:
resolved "https://registry.yarnpkg.com/toggle-selection/-/toggle-selection-1.0.6.tgz#6e45b1263f2017fa0acc7d89d78b15b8bf77da32"
integrity sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==
tom-select@2.4.1:
version "2.4.1"
resolved "https://registry.yarnpkg.com/tom-select/-/tom-select-2.4.1.tgz#6a0b6df8af3df7b09b22dd965eb75ce4d1c547bc"
integrity sha512-adI8H8+wk8RRzHYLQ3bXSk2Q+FAq/kzAATrcWlJ2fbIrEzb0VkwaXzKHTAlBwSJrhqbPJvhV/0eypFkED/nAug==
tom-select@2.4.2:
version "2.4.2"
resolved "https://registry.yarnpkg.com/tom-select/-/tom-select-2.4.2.tgz#9764faf6cba51f6571d03a79bb7c1cac1cac7a5a"
integrity sha512-2RWjkL3gMDz9E+u8w+tQy9JWsYq8gaSytEVeugKYDeMus6ZtxT1HttLPnXsfHCnBPlsNubVyj5gtUeN+S+bcpA==
dependencies:
"@orchidjs/sifter" "^1.1.0"
"@orchidjs/unicode-variants" "^1.1.2"

View File

@@ -1,3 +1,3 @@
version: "4.2.1"
version: "4.2.4"
edition: "Community"
published: "2025-01-08"
published: "2025-02-21"

View File

@@ -17,6 +17,7 @@
<meta charset="UTF-8" />
<meta name="viewport" content="initial-scale=1, maximum-scale=5, width=device-width, viewport-fit=cover" />
<meta name="htmx-config" content='{"scrollBehavior": "auto"}'>
<meta name="hostname" content="{{ settings.HOSTNAME }}" />
{# Page title #}
<title>{% block title %}{% trans "Home" %}{% endblock %} | NetBox</title>

View File

@@ -103,7 +103,7 @@
<tr>
<th scope="row" class="border-0 ps-3">{% trans "Protection rules" %}</th>
{% if config.PROTECTION_RULES %}
<td class="border-0"><pre>{{ config.PROTECTION_RULES|json }}</pre></td>
<td class="border-0"><pre>{{ config.PROTECTION_RULES }}</pre></td>
{% else %}
<td class="border-0">{{ ''|placeholder }}</td>
{% endif %}

View File

@@ -5,7 +5,7 @@
<div class="list-group-item px-1 py-2">
<a href="{{ entry.link }}" class="text-body">{{ entry.title }}</a>
<div class="text-secondary">
{{ entry.summary|safe }}
{{ entry.summary }}
</div>
</div>
{% empty %}

View File

@@ -1,4 +1,4 @@
<div class="btn-group btn-group-sm" role="group">
<a href="?format=json" type="button" class="btn btn-outline-dark{% if format == 'json' %} active{% endif %}">JSON</a>
<a href="?format=yaml" type="button" class="btn btn-outline-dark{% if format == 'yaml' %} active{% endif %}">YAML</a>
<a href="?format=json" type="button" class="btn {% if format == 'json' %}btn-primary{% else %}btn-outline-secondary{% endif %}">JSON</a>
<a href="?format=yaml" type="button" class="btn {% if format == 'yaml' %}btn-primary{% else %}btn-outline-secondary{% endif %}">YAML</a>
</div>

View File

@@ -1,4 +1,5 @@
{% extends 'dcim/device/base.html' %}
{% extends base_template %}
{% load helpers %}
{% load static %}
{% load i18n %}
@@ -67,7 +68,7 @@
{% endif %}
{% else %}
<div class="alert alert-info">
{% trans "No configuration template has been assigned for this device." %}
{% trans "No configuration template has been assigned." %}
</div>
{% endif %}
</div>

View File

@@ -53,7 +53,7 @@
<div class="dropdown-menu">
{% for level, name in log_levels.items %}
<a class="dropdown-item d-flex justify-content-between" href="{% url 'extras:script_result' job_pk=job.pk %}?log_threshold={{ level }}">
{{ name }}{% if forloop.first %} ({% trans "All" %}){% endif %}
{{ name }}{% if forloop.counter == 1 %} ({% trans "All" %}){% elif forloop.counter == 2 %} ({% trans "Default" %}){% endif %}
{% if level == log_threshold %}<span class="badge bg-green ms-auto"></span>{% endif %}
</a>
{% endfor %}

View File

@@ -55,22 +55,23 @@
</div>
<div class="card">
<h2 class="card-header">{% trans "Tagged Item Types" %}</h2>
<table class="table table-hover attr-table">
<ul class="list-group list-group-flush" role="presentation">
{% for object_type in object_types %}
<tr>
<td>{{ object_type.content_type.name|bettertitle }}</td>
<td>
{% with viewname=object_type.content_type.model_class|validated_viewname:"list" %}
{% if viewname %}
<a href="{% url viewname %}?tag={{ object.slug }}">{{ object_type.item_count }}</a>
{% else %}
{{ object_type.item_count }}
{% endif %}
{% endwith %}
</td>
</tr>
{% with viewname=object_type.content_type.model_class|validated_viewname:"list" %}
{% if viewname %}
<a href="{% url viewname %}?tag={{ object.slug }}" class="list-group-item list-group-item-action d-flex justify-content-between">
{{ object_type.content_type.name|bettertitle }}
<span class="badge text-bg-primary rounded-pill">{{ object_type.item_count }}</span>
</a>
{% else %}
<li class="list-group-item list-group-item-action d-flex justify-content-between">
{{ object_type.content_type.name|bettertitle }}
<span class="badge text-bg-primary rounded-pill">{{ object_type.item_count }}</span>
</li>
{% endif %}
{% endwith %}
{% endfor %}
</table>
</ul>
</div>
{% plugin_right_page object %}
</div>
@@ -79,7 +80,7 @@
<div class="col col-md-12">
<div class="card">
<h2 class="card-header">{% trans "Tagged Objects" %}</h2>
<div class="card-body table-responsive">
<div class="table-responsive">
{% render_table taggeditem_table 'inc/table.html' %}
{% include 'inc/paginator.html' with paginator=taggeditem_table.paginator page=taggeditem_table.page %}
</div>

View File

@@ -19,6 +19,8 @@
</a>
{% endif %}
{% endwith %}
{% empty %}
<span class="list-group-item text-muted">{% trans "None" %}</span>
{% endfor %}
</ul>
</div>

View File

@@ -1,75 +0,0 @@
{% extends 'virtualization/virtualmachine/base.html' %}
{% load static %}
{% load i18n %}
{% block title %}{{ object }} - {% trans "Config" %}{% endblock %}
{% block content %}
<div class="row">
<div class="col-5">
<div class="card">
<h2 class="card-header">{% trans "Config Template" %}</h2>
<table class="table table-hover attr-table">
<tr>
<th scope="row">{% trans "Config Template" %}</th>
<td>{{ config_template|linkify|placeholder }}</td>
</tr>
<tr>
<th scope="row">{% trans "Data Source" %}</th>
<td>{{ config_template.data_file.source|linkify|placeholder }}</td>
</tr>
<tr>
<th scope="row">{% trans "Data File" %}</th>
<td>{{ config_template.data_file|linkify|placeholder }}</td>
</tr>
</table>
</div>
</div>
<div class="col-7">
<div class="card">
<div class="accordion accordion-flush" id="renderConfig">
<div class="card-body">
<div class="accordion-item">
<h2 class="accordion-header" id="renderConfigHeading">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapsedRenderConfig" aria-expanded="false" aria-controls="collapsedRenderConfig">
{% trans "Context Data" %}
</button>
</h2>
<div id="collapsedRenderConfig" class="accordion-collapse collapse" aria-labelledby="renderConfigHeading" data-bs-parent="#renderConfig">
<div class="accordion-body">
<pre class="card-body">{{ context_data|pprint }}</pre>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col">
{% if config_template %}
{% if rendered_config %}
<div class="card">
<h2 class="card-header d-flex justify-content-between">
{% trans "Rendered Config" %}
<a href="?export=True" class="btn btn-primary lh-1" role="button">
<i class="mdi mdi-download" aria-hidden="true"></i> {% trans "Download" %}
</a>
</h2>
<pre class="card-body">{{ rendered_config }}</pre>
</div>
{% else %}
<div class="alert alert-warning">
<h4 class="alert-title mb-1">{% trans "Error rendering template" %}</h4>
{% trans error_message %}
</div>
{% endif %}
{% else %}
<div class="alert alert-info">
{% trans "No configuration template has been assigned for this virtual machine." %}
</div>
{% endif %}
</div>
</div>
{% endblock %}

View File

@@ -4,10 +4,10 @@
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
# Translators:
# czarnian, 2024
# Jeremy Stretch, 2024
# Pavel Valach, 2024
# Matěj Gordon, 2025
# czarnian, 2025
# Jeremy Stretch, 2025
#
#, fuzzy
msgid ""
@@ -16,7 +16,7 @@ msgstr ""
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-01-04 05:02+0000\n"
"PO-Revision-Date: 2023-10-30 17:48+0000\n"
"Last-Translator: Matěj Gordon, 2025\n"
"Last-Translator: Jeremy Stretch, 2025\n"
"Language-Team: Czech (https://app.transifex.com/netbox-community/teams/178115/cs/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@@ -64,7 +64,7 @@ msgstr "Naposledy použitý"
#: netbox/templates/users/token.html:47 netbox/users/forms/bulk_edit.py:122
#: netbox/users/forms/model_forms.py:124
msgid "Allowed IPs"
msgstr "Povolené IP adresy"
msgstr "Povolené adresy IP"
#: netbox/account/views.py:114
#, python-brace-format
@@ -179,7 +179,7 @@ msgstr "Region (zkratka)"
#: netbox/ipam/filtersets.py:974 netbox/virtualization/filtersets.py:58
#: netbox/virtualization/filtersets.py:186
msgid "Site group (ID)"
msgstr "Skupina stránek (ID)"
msgstr "Skupina st (ID)"
#: netbox/circuits/filtersets.py:51 netbox/circuits/filtersets.py:218
#: netbox/dcim/filtersets.py:135 netbox/dcim/filtersets.py:232
@@ -191,7 +191,7 @@ msgstr "Skupina stránek (ID)"
#: netbox/virtualization/filtersets.py:65
#: netbox/virtualization/filtersets.py:193
msgid "Site group (slug)"
msgstr "Skupina stránek (slug)"
msgstr "Skupina míst (zkratka)"
#: netbox/circuits/filtersets.py:56 netbox/circuits/forms/bulk_edit.py:188
#: netbox/circuits/forms/bulk_edit.py:216
@@ -252,7 +252,7 @@ msgstr "Skupina stránek (slug)"
#: netbox/vpn/forms/filtersets.py:266 netbox/wireless/forms/model_forms.py:76
#: netbox/wireless/forms/model_forms.py:118
msgid "Site"
msgstr "Stránky"
msgstr "Místo"
#: netbox/circuits/filtersets.py:62 netbox/circuits/filtersets.py:229
#: netbox/circuits/filtersets.py:274 netbox/dcim/filtersets.py:242
@@ -262,7 +262,7 @@ msgstr "Stránky"
#: netbox/virtualization/filtersets.py:75
#: netbox/virtualization/filtersets.py:203 netbox/vpn/filtersets.py:363
msgid "Site (slug)"
msgstr "Místo (slug)"
msgstr "Místo (zkratka)"
#: netbox/circuits/filtersets.py:67
msgid "ASN (ID)"
@@ -316,7 +316,7 @@ msgstr "Typ okruhu (URL zkratka)"
#: netbox/ipam/filtersets.py:985 netbox/virtualization/filtersets.py:69
#: netbox/virtualization/filtersets.py:197 netbox/vpn/filtersets.py:368
msgid "Site (ID)"
msgstr "Stránky (ID)"
msgstr "Místo (ID)"
#: netbox/circuits/filtersets.py:233 netbox/circuits/filtersets.py:237
msgid "Termination A (ID)"
@@ -371,15 +371,15 @@ msgstr "Síť poskytovatele (ID)"
#: netbox/circuits/filtersets.py:335
msgid "Circuit (ID)"
msgstr "Obvod (ID)"
msgstr "Okruh (ID)"
#: netbox/circuits/filtersets.py:341
msgid "Circuit (CID)"
msgstr "Obvod (CID)"
msgstr "Okruh (CID)"
#: netbox/circuits/filtersets.py:345
msgid "Circuit group (ID)"
msgstr "Skupina obvodů (ID)"
msgstr "Skupina okruhů (ID)"
#: netbox/circuits/filtersets.py:351
msgid "Circuit group (slug)"
@@ -804,7 +804,7 @@ msgstr "Datum ukončení"
#: netbox/circuits/forms/bulk_edit.py:158
#: netbox/circuits/forms/filtersets.py:186
msgid "Commit rate (Kbps)"
msgstr "Rychlost odevzdání (Kbps)"
msgstr "Smluvní rychlost (Kbps)"
#: netbox/circuits/forms/bulk_edit.py:173
#: netbox/circuits/forms/model_forms.py:112
@@ -1042,7 +1042,7 @@ msgstr "Region"
#: netbox/virtualization/forms/filtersets.py:138
#: netbox/virtualization/forms/model_forms.py:98
msgid "Site group"
msgstr "Skupina stránek"
msgstr "Skupina st"
#: netbox/circuits/forms/filtersets.py:65
#: netbox/circuits/forms/filtersets.py:83
@@ -1160,19 +1160,19 @@ msgstr "barva"
#: netbox/circuits/models/circuits.py:36
msgid "circuit type"
msgstr "typ obvodu"
msgstr "typ okruhu"
#: netbox/circuits/models/circuits.py:37
msgid "circuit types"
msgstr "typy obvodů"
msgstr "typy okruhů"
#: netbox/circuits/models/circuits.py:48
msgid "circuit ID"
msgstr "ID obvodu"
msgstr "ID okruhu"
#: netbox/circuits/models/circuits.py:49
msgid "Unique circuit ID"
msgstr "Jedinečné ID obvodu"
msgstr "Jedinečné ID okruhu"
#: netbox/circuits/models/circuits.py:69 netbox/core/models/data.py:52
#: netbox/core/models/jobs.py:85 netbox/dcim/models/cables.py:49
@@ -1194,11 +1194,11 @@ msgstr "nainstalován"
#: netbox/circuits/models/circuits.py:89
msgid "terminates"
msgstr "ukončí"
msgstr "končí"
#: netbox/circuits/models/circuits.py:94
msgid "commit rate (Kbps)"
msgstr "rychlost odevzdání (Kbps)"
msgstr "smluvní rychlost (Kbps)"
#: netbox/circuits/models/circuits.py:95
msgid "Committed rate"
@@ -1214,11 +1214,11 @@ msgstr "okruhy"
#: netbox/circuits/models/circuits.py:170
msgid "circuit group"
msgstr "skupina obvodů"
msgstr "skupina okruhů"
#: netbox/circuits/models/circuits.py:171
msgid "circuit groups"
msgstr "skupiny obvodů"
msgstr "skupiny okruhů"
#: netbox/circuits/models/circuits.py:195 netbox/ipam/models/fhrp.py:93
#: netbox/tenancy/models/contacts.py:134
@@ -1227,7 +1227,7 @@ msgstr "přednost"
#: netbox/circuits/models/circuits.py:213
msgid "Circuit group assignment"
msgstr "Přiřazení skupiny obvodů"
msgstr "Přiřazení skupiny okruhů"
#: netbox/circuits/models/circuits.py:214
msgid "Circuit group assignments"
@@ -1235,7 +1235,7 @@ msgstr "Přiřazení skupin obvodů"
#: netbox/circuits/models/circuits.py:240
msgid "termination"
msgstr "zakončení"
msgstr ""
#: netbox/circuits/models/circuits.py:257
msgid "port speed (Kbps)"
@@ -1297,14 +1297,11 @@ msgstr "zakončení okruhů"
msgid ""
"A circuit termination must attach to either a site or a provider network."
msgstr ""
"Zakončení okruhu se musí připojit buď k místu, nebo k síti poskytovatele."
#: netbox/circuits/models/circuits.py:310
msgid ""
"A circuit termination cannot attach to both a site and a provider network."
msgstr ""
"Zakončení okruhu se nemůže připojit jak k síti webu, tak k síti "
"poskytovatele."
#: netbox/circuits/models/providers.py:22
#: netbox/circuits/models/providers.py:66
@@ -1534,7 +1531,7 @@ msgstr "Strana Z"
#: netbox/circuits/tables/circuits.py:77
#: netbox/templates/circuits/circuit.html:55
msgid "Commit Rate"
msgstr "Míra odevzdání"
msgstr "Smluvní rychlost"
#: netbox/circuits/tables/circuits.py:80
#: netbox/circuits/tables/providers.py:48
@@ -1563,7 +1560,7 @@ msgstr "Míra odevzdání"
#: netbox/vpn/tables/tunnels.py:61 netbox/wireless/tables/wirelesslan.py:27
#: netbox/wireless/tables/wirelesslan.py:58
msgid "Comments"
msgstr "Komentář"
msgstr "Komentáře"
#: netbox/circuits/tables/circuits.py:86
#: netbox/templates/tenancy/contact.html:84
@@ -1586,12 +1583,12 @@ msgstr "Počet ASN"
#: netbox/circuits/views.py:331
#, python-brace-format
msgid "No terminations have been defined for circuit {circuit}."
msgstr "Pro obvod nebyla definována žádná zakončení {circuit}."
msgstr "Pro okruh {circuit} nebyla definována žádná zakončení ."
#: netbox/circuits/views.py:380
#, python-brace-format
msgid "Swapped terminations for circuit {circuit}."
msgstr "Vyměněné zakončení pro obvod {circuit}."
msgstr "Vyměněná zakončení pro okruh {circuit}."
#: netbox/core/api/views.py:39
msgid "This user does not have permission to synchronize this data source."
@@ -1620,7 +1617,7 @@ msgstr "Dokončeno"
#: netbox/dcim/choices.py:187 netbox/dcim/choices.py:239
#: netbox/dcim/choices.py:1609 netbox/virtualization/choices.py:47
msgid "Failed"
msgstr "Neuspěl"
msgstr "Selhalo"
#: netbox/core/choices.py:35 netbox/netbox/navigation/menu.py:335
#: netbox/netbox/navigation/menu.py:339
@@ -1647,7 +1644,7 @@ msgstr "Naplánováno"
#: netbox/core/choices.py:56
msgid "Running"
msgstr "Běh"
msgstr "Běží"
#: netbox/core/choices.py:58
msgid "Errored"
@@ -1656,7 +1653,7 @@ msgstr "Chyba"
#: netbox/core/choices.py:87 netbox/core/tables/plugins.py:63
#: netbox/templates/generic/object.html:61
msgid "Updated"
msgstr "aktualizováno"
msgstr "Aktualizováno"
#: netbox/core/choices.py:88
msgid "Deleted"
@@ -1725,7 +1722,7 @@ msgstr "Tajný přístupový klíč AWS"
#: netbox/core/events.py:27
msgid "Object created"
msgstr "Vytvořený objekt"
msgstr "Objekt vytvořen"
#: netbox/core/events.py:28
msgid "Object updated"
@@ -1737,7 +1734,7 @@ msgstr "Objekt odstraněn"
#: netbox/core/events.py:30
msgid "Job started"
msgstr "Práce byla zahájena"
msgstr "Úloha zahájena"
#: netbox/core/events.py:31
msgid "Job completed"
@@ -1850,7 +1847,7 @@ msgstr "Vytvořeno po"
#: netbox/core/forms/filtersets.py:89
msgid "Created before"
msgstr "Vytvořeno dříve"
msgstr "Vytvořeno před"
#: netbox/core/forms/filtersets.py:94
msgid "Scheduled after"
@@ -1858,7 +1855,7 @@ msgstr "Naplánováno po"
#: netbox/core/forms/filtersets.py:99
msgid "Scheduled before"
msgstr "Naplánováno dříve"
msgstr "Naplánováno před"
#: netbox/core/forms/filtersets.py:104
msgid "Started after"
@@ -1866,7 +1863,7 @@ msgstr "Začalo po"
#: netbox/core/forms/filtersets.py:109
msgid "Started before"
msgstr "Začalo dříve"
msgstr "Začalo před"
#: netbox/core/forms/filtersets.py:114
msgid "Completed after"
@@ -1905,7 +1902,7 @@ msgstr "Po"
#: netbox/core/forms/filtersets.py:144 netbox/extras/forms/filtersets.py:450
msgid "Before"
msgstr "Dříve"
msgstr "Před"
#: netbox/core/forms/filtersets.py:148 netbox/core/tables/change_logging.py:29
#: netbox/extras/forms/model_forms.py:396
@@ -1941,7 +1938,7 @@ msgstr ""
#: netbox/core/forms/model_forms.py:153
#: netbox/templates/dcim/rack_elevation_list.html:6
msgid "Rack Elevations"
msgstr "Výšky stojanů"
msgstr "Přehled stojanů"
#: netbox/core/forms/model_forms.py:157 netbox/dcim/choices.py:1520
#: netbox/dcim/forms/bulk_edit.py:984 netbox/dcim/forms/bulk_edit.py:1372
@@ -2259,16 +2256,16 @@ msgstr "ID úlohy"
#: netbox/core/models/jobs.py:112
msgid "job"
msgstr "práce"
msgstr "úloha"
#: netbox/core/models/jobs.py:113
msgid "jobs"
msgstr "pracovní místa"
msgstr "úlohy"
#: netbox/core/models/jobs.py:136
#, python-brace-format
msgid "Jobs cannot be assigned to this object type ({type})."
msgstr "K tomuto typu objektu nelze přiřadit úlohy ({type})."
msgstr "K tomuto typu objektu ({type}) nelze přiřadit úlohy."
#: netbox/core/models/jobs.py:190
#, python-brace-format
@@ -2278,7 +2275,7 @@ msgstr "Neplatný stav pro ukončení úlohy. Možnosti jsou: {choices}"
#: netbox/core/models/jobs.py:221
msgid ""
"enqueue() cannot be called with values for both schedule_at and immediate."
msgstr "enqueue () nelze volat s hodnotami pro schedule_at a instant."
msgstr "enqueue() nelze volat s hodnotami pro schedule_at a ihned zároveň."
#: netbox/core/signals.py:126
#, python-brace-format
@@ -2396,7 +2393,7 @@ msgstr "Hostitel"
#: netbox/core/tables/tasks.py:50 netbox/ipam/forms/filtersets.py:535
msgid "Port"
msgstr "Přístav"
msgstr "Port"
#: netbox/core/tables/tasks.py:54
msgid "DB"
@@ -2445,7 +2442,7 @@ msgstr "Nebyli nalezeni žádní pracovníci"
#: netbox/core/views.py:90
#, python-brace-format
msgid "Queued job #{id} to sync {datasource}"
msgstr "Úloha ve frontě #{id} synchronizovat {datasource}"
msgstr "Úloha #{id} k synchronizaci {datasource} zařazena do fronty."
#: netbox/core/views.py:319
#, python-brace-format
@@ -2455,12 +2452,12 @@ msgstr "Obnovená revize konfigurace #{id}"
#: netbox/core/views.py:412 netbox/core/views.py:455 netbox/core/views.py:531
#, python-brace-format
msgid "Job {job_id} not found"
msgstr "Práce {job_id} nenalezeno"
msgstr "Úloha {job_id} nenalezena"
#: netbox/core/views.py:463
#, python-brace-format
msgid "Job {id} has been deleted."
msgstr "Práce {id} byl vymazán."
msgstr "Úloha {id} byla vymazána."
#: netbox/core/views.py:465
#, python-brace-format
@@ -2470,22 +2467,22 @@ msgstr "Chyba při mazání úlohy {id}: {error}"
#: netbox/core/views.py:478 netbox/core/views.py:496
#, python-brace-format
msgid "Job {id} not found."
msgstr "Práce {id} nenalezeno."
msgstr "Úloha {id} nenalezena."
#: netbox/core/views.py:484
#, python-brace-format
msgid "Job {id} has been re-enqueued."
msgstr "Práce {id} byla znovu zařazena do fronty."
msgstr "Úloha {id} byla znovu zařazena do fronty."
#: netbox/core/views.py:519
#, python-brace-format
msgid "Job {id} has been enqueued."
msgstr "Práce {id} byl zařazen do fronty."
msgstr "Úloha {id} byla zařazena do fronty."
#: netbox/core/views.py:538
#, python-brace-format
msgid "Job {id} has been stopped."
msgstr "Práce {id} byl zastaven."
msgstr "Úloha {id} byla zastavena."
#: netbox/core/views.py:540
#, python-brace-format
@@ -2535,7 +2532,7 @@ msgstr "4-sloupový rám"
#: netbox/dcim/choices.py:67
msgid "4-post cabinet"
msgstr "4-sloupová skříňka"
msgstr "4-sloupová skříň"
#: netbox/dcim/choices.py:68
msgid "Wall-mounted frame"
@@ -2547,7 +2544,7 @@ msgstr "Nástěnný rám (vertikální)"
#: netbox/dcim/choices.py:70
msgid "Wall-mounted cabinet"
msgstr "Nástěnná skříňka"
msgstr "Nástěnná skříň"
#: netbox/dcim/choices.py:71
msgid "Wall-mounted cabinet (vertical)"
@@ -2582,7 +2579,7 @@ msgstr "Milimetry"
#: netbox/dcim/choices.py:115 netbox/dcim/choices.py:1555
msgid "Inches"
msgstr "palce"
msgstr "Palce"
#: netbox/dcim/choices.py:136 netbox/dcim/choices.py:207
#: netbox/dcim/choices.py:254
@@ -2679,12 +2676,12 @@ msgstr "Zdola nahoru"
#: netbox/dcim/choices.py:214
msgid "Top to bottom"
msgstr "Nahoru dolů"
msgstr "Shora dolů"
#: netbox/dcim/choices.py:215 netbox/dcim/choices.py:259
#: netbox/dcim/choices.py:1305
msgid "Passive"
msgstr "pasivní"
msgstr "Pasivní"
#: netbox/dcim/choices.py:216
msgid "Mixed"
@@ -2802,17 +2799,17 @@ msgstr "Auto"
#: netbox/dcim/choices.py:1265
msgid "Access"
msgstr "Přístup"
msgstr "Přístupový"
#: netbox/dcim/choices.py:1266 netbox/ipam/tables/vlans.py:172
#: netbox/ipam/tables/vlans.py:217
#: netbox/templates/dcim/inc/interface_vlans_table.html:7
msgid "Tagged"
msgstr "Označeno"
msgstr "Značkovaný"
#: netbox/dcim/choices.py:1267
msgid "Tagged (All)"
msgstr "Označeno (Vše)"
msgstr "Značkovaný (Vše)"
#: netbox/dcim/choices.py:1296
msgid "IEEE Standard"
@@ -2888,7 +2885,7 @@ msgstr "Gramy"
#: netbox/dcim/choices.py:1572 netbox/templates/dcim/device.html:328
#: netbox/templates/dcim/rack.html:108
msgid "Pounds"
msgstr "libry"
msgstr "Libry"
#: netbox/dcim/choices.py:1573
msgid "Ounces"
@@ -2896,7 +2893,7 @@ msgstr "Unce"
#: netbox/dcim/choices.py:1620
msgid "Redundant"
msgstr "Redundantní"
msgstr "Zdvojený"
#: netbox/dcim/choices.py:1641
msgid "Single phase"
@@ -2922,15 +2919,15 @@ msgstr "Nadřazená oblast (ID)"
#: netbox/dcim/filtersets.py:92
msgid "Parent region (slug)"
msgstr "Nadřazená oblast (URL zkratka)"
msgstr "Nadřazená oblast (zkratka)"
#: netbox/dcim/filtersets.py:116
msgid "Parent site group (ID)"
msgstr "Nadřazená skupina webů (ID)"
msgstr "Nadřazená skupina míst (ID)"
#: netbox/dcim/filtersets.py:122
msgid "Parent site group (slug)"
msgstr "Nadřazená skupina stránek (slimák)"
msgstr "Nadřazená skupina míst (zkratka)"
#: netbox/dcim/filtersets.py:164 netbox/extras/filtersets.py:364
#: netbox/ipam/filtersets.py:843 netbox/ipam/filtersets.py:995
@@ -4231,7 +4228,7 @@ msgstr "Šířka musí být nastavena, pokud není zadán typ stojanu."
#: netbox/dcim/forms/bulk_import.py:326
msgid "U height must be set if not specifying a rack type."
msgstr ""
msgstr "Pokud není zadán typ stojanu, musí být nastavena výška U."
#: netbox/dcim/forms/bulk_import.py:334
msgid "Parent site"
@@ -4890,6 +4887,11 @@ msgid ""
"present, will be automatically replaced with the position value when "
"creating a new module."
msgstr ""
"Pro hromadné vytváření jsou podporovány alfanumerické rozsahy. Smíšené "
"případy a typy v rámci jednoho rozsahu nejsou podporovány (příklad: "
"<code>[ge, xe] -0/0/ [0-9]</code>). Žeton <code>{module}</code>, pokud je "
"přítomen, bude automaticky nahrazen hodnotou pozice při vytváření nového "
"modulu."
#: netbox/dcim/forms/model_forms.py:1094
msgid "Console port template"
@@ -9595,11 +9597,11 @@ msgstr "Nastavte to jako primární IP pro přiřazené zařízení"
#: netbox/ipam/forms/bulk_import.py:330
msgid "Is out-of-band"
msgstr ""
msgstr "Je mimo pásmo"
#: netbox/ipam/forms/bulk_import.py:331
msgid "Designate this as the out-of-band IP address for the assigned device"
msgstr ""
msgstr "Určete tuto adresu jako mimopásmovou IP adresu přiřazeného zařízení"
#: netbox/ipam/forms/bulk_import.py:371
msgid "No device or virtual machine specified; cannot set as primary IP"
@@ -9609,11 +9611,11 @@ msgstr ""
#: netbox/ipam/forms/bulk_import.py:375
msgid "No device specified; cannot set as out-of-band IP"
msgstr ""
msgstr "Není určeno žádné zařízení; nelze nastavit jako IP mimo pásmo"
#: netbox/ipam/forms/bulk_import.py:379
msgid "Cannot set out-of-band IP for virtual machines"
msgstr ""
msgstr "Nelze nastavit IP mimo pásmo pro virtuální počítače"
#: netbox/ipam/forms/bulk_import.py:383
msgid "No interface specified; cannot set as primary IP"
@@ -9621,7 +9623,7 @@ msgstr "Není určeno žádné rozhraní; nelze nastavit jako primární IP"
#: netbox/ipam/forms/bulk_import.py:387
msgid "No interface specified; cannot set as out-of-band IP"
msgstr ""
msgstr "Není určeno žádné rozhraní; nelze nastavit jako IP mimo pásmo"
#: netbox/ipam/forms/bulk_import.py:422
msgid "Auth type"
@@ -9780,7 +9782,7 @@ msgstr "Řada ASN"
#: netbox/ipam/forms/model_forms.py:231
msgid "Site/VLAN Assignment"
msgstr "Přiřazení webu/VLAN"
msgstr ""
#: netbox/ipam/forms/model_forms.py:259 netbox/templates/ipam/iprange.html:10
msgid "IP Range"
@@ -9798,7 +9800,7 @@ msgstr "Nastavte z něj primární IP pro zařízení/virtuální počítač"
#: netbox/ipam/forms/model_forms.py:314
msgid "Make this the out-of-band IP for the device"
msgstr ""
msgstr "Nastavte z tohoto pole IP mimo pásmo zařízení"
#: netbox/ipam/forms/model_forms.py:329
msgid "NAT IP (Inside)"
@@ -9811,10 +9813,12 @@ msgstr "IP adresu lze přiřadit pouze jednomu objektu."
#: netbox/ipam/forms/model_forms.py:398
msgid "Cannot reassign primary IP address for the parent device/VM"
msgstr ""
"Nelze znovu přiřadit primární adresu IP pro nadřazené zařízení/virtuální "
"počítač"
#: netbox/ipam/forms/model_forms.py:402
msgid "Cannot reassign out-of-Band IP address for the parent device"
msgstr ""
msgstr "Nelze znovu přiřadit IP adresu mimo pásmo pro nadřazené zařízení"
#: netbox/ipam/forms/model_forms.py:412
msgid ""
@@ -9827,6 +9831,8 @@ msgid ""
"Only IP addresses assigned to a device interface can be designated as the "
"out-of-band IP for a device."
msgstr ""
"Pouze IP adresy přiřazené k rozhraní zařízení mohou být označeny jako IP "
"adresy mimo pásmo zařízení."
#: netbox/ipam/forms/model_forms.py:508
msgid "Virtual IP Address"
@@ -10220,12 +10226,12 @@ msgstr "Nelze nastavit scope_id bez scope_type."
#: netbox/ipam/models/vlans.py:105
#, python-brace-format
msgid "Starting VLAN ID in range ({value}) cannot be less than {minimum}"
msgstr ""
msgstr "Spuštění VLAN ID v dosahu ({value}) nemůže být menší než {minimum}"
#: netbox/ipam/models/vlans.py:111
#, python-brace-format
msgid "Ending VLAN ID in range ({value}) cannot exceed {maximum}"
msgstr ""
msgstr "Ukončení VLAN ID v rozsahu ({value}) nesmí překročit {maximum}"
#: netbox/ipam/models/vlans.py:118
#, python-brace-format
@@ -10233,6 +10239,8 @@ msgid ""
"Ending VLAN ID in range must be greater than or equal to the starting VLAN "
"ID ({range})"
msgstr ""
"Koncové ID VLAN v rozsahu musí být větší nebo roven počátečnímu ID VLAN "
"({range})"
#: netbox/ipam/models/vlans.py:124
msgid "Ranges cannot overlap."
@@ -12587,7 +12595,7 @@ msgstr "Chyba při vykreslování šablony"
#: netbox/templates/dcim/device/render_config.html:70
msgid "No configuration template has been assigned for this device."
msgstr "Pro toto zařízení nebyla přiřazena žádná konfigurační šablona."
msgstr ""
#: netbox/templates/dcim/device_edit.html:44
msgid "Parent Bay"
@@ -13852,7 +13860,7 @@ msgstr "Centrum nápovědy"
#: netbox/templates/inc/user_menu.html:41
msgid "Django Admin"
msgstr "Správce Django"
msgstr ""
#: netbox/templates/inc/user_menu.html:61
msgid "Log Out"
@@ -14266,7 +14274,6 @@ msgstr "Přidat virtuální disk"
#: netbox/templates/virtualization/virtualmachine/render_config.html:70
msgid "No configuration template has been assigned for this virtual machine."
msgstr ""
"Pro tento virtuální počítač nebyla přiřazena žádná konfigurační šablona."
#: netbox/templates/vpn/ikepolicy.html:10
#: netbox/templates/vpn/ipsecprofile.html:33 netbox/vpn/tables/crypto.py:166
@@ -15365,7 +15372,6 @@ msgid ""
"{device} belongs to a different site ({device_site}) than the cluster "
"({cluster_site})"
msgstr ""
"{device} patří k jinému webu ({device_site}) než cluster ({cluster_site})"
#: netbox/virtualization/forms/model_forms.py:192
msgid "Optionally pin this VM to a specific host device within the cluster"
@@ -16098,7 +16104,7 @@ msgstr "bezdrátové spoje"
#: netbox/wireless/models.py:236
msgid "Must specify a unit when setting a wireless distance"
msgstr "Při nastavování bezdrátové vzdálenosti je nutné zadat jednotku"
msgstr ""
#: netbox/wireless/models.py:242 netbox/wireless/models.py:248
#, python-brace-format

View File

@@ -6,17 +6,17 @@
# Translators:
# Jeff Gehlbach, 2024
# ch, 2024
# Frederik Spang Thomsen <frederik@progras.dk>, 2024
# Jeremy Stretch, 2024
# Frederik Spang <fst@progras.dk>, 2024
# Jeremy Stretch, 2025
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-12-12 05:02+0000\n"
"POT-Creation-Date: 2025-01-04 05:02+0000\n"
"PO-Revision-Date: 2023-10-30 17:48+0000\n"
"Last-Translator: Jeremy Stretch, 2024\n"
"Last-Translator: Jeremy Stretch, 2025\n"
"Language-Team: Danish (https://app.transifex.com/netbox-community/teams/178115/da/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@@ -152,7 +152,7 @@ msgstr "Inaktiv"
#: netbox/dcim/filtersets.py:464 netbox/dcim/filtersets.py:1021
#: netbox/dcim/filtersets.py:1368 netbox/dcim/filtersets.py:1903
#: netbox/dcim/filtersets.py:2146 netbox/dcim/filtersets.py:2204
#: netbox/ipam/filtersets.py:339 netbox/ipam/filtersets.py:959
#: netbox/ipam/filtersets.py:341 netbox/ipam/filtersets.py:961
#: netbox/virtualization/filtersets.py:45
#: netbox/virtualization/filtersets.py:173 netbox/vpn/filtersets.py:358
msgid "Region (ID)"
@@ -164,8 +164,8 @@ msgstr "Område (ID)"
#: netbox/dcim/filtersets.py:471 netbox/dcim/filtersets.py:1028
#: netbox/dcim/filtersets.py:1375 netbox/dcim/filtersets.py:1910
#: netbox/dcim/filtersets.py:2153 netbox/dcim/filtersets.py:2211
#: netbox/extras/filtersets.py:509 netbox/ipam/filtersets.py:346
#: netbox/ipam/filtersets.py:966 netbox/virtualization/filtersets.py:52
#: netbox/extras/filtersets.py:509 netbox/ipam/filtersets.py:348
#: netbox/ipam/filtersets.py:968 netbox/virtualization/filtersets.py:52
#: netbox/virtualization/filtersets.py:180 netbox/vpn/filtersets.py:353
msgid "Region (slug)"
msgstr "Region (slug)"
@@ -175,8 +175,8 @@ msgstr "Region (slug)"
#: netbox/dcim/filtersets.py:346 netbox/dcim/filtersets.py:477
#: netbox/dcim/filtersets.py:1034 netbox/dcim/filtersets.py:1381
#: netbox/dcim/filtersets.py:1916 netbox/dcim/filtersets.py:2159
#: netbox/dcim/filtersets.py:2217 netbox/ipam/filtersets.py:352
#: netbox/ipam/filtersets.py:972 netbox/virtualization/filtersets.py:58
#: netbox/dcim/filtersets.py:2217 netbox/ipam/filtersets.py:354
#: netbox/ipam/filtersets.py:974 netbox/virtualization/filtersets.py:58
#: netbox/virtualization/filtersets.py:186
msgid "Site group (ID)"
msgstr "Områdegruppe (ID)"
@@ -187,7 +187,7 @@ msgstr "Områdegruppe (ID)"
#: netbox/dcim/filtersets.py:1041 netbox/dcim/filtersets.py:1388
#: netbox/dcim/filtersets.py:1923 netbox/dcim/filtersets.py:2166
#: netbox/dcim/filtersets.py:2224 netbox/extras/filtersets.py:515
#: netbox/ipam/filtersets.py:359 netbox/ipam/filtersets.py:979
#: netbox/ipam/filtersets.py:361 netbox/ipam/filtersets.py:981
#: netbox/virtualization/filtersets.py:65
#: netbox/virtualization/filtersets.py:193
msgid "Site group (slug)"
@@ -257,8 +257,8 @@ msgstr "Område"
#: netbox/circuits/filtersets.py:62 netbox/circuits/filtersets.py:229
#: netbox/circuits/filtersets.py:274 netbox/dcim/filtersets.py:242
#: netbox/dcim/filtersets.py:363 netbox/dcim/filtersets.py:458
#: netbox/extras/filtersets.py:531 netbox/ipam/filtersets.py:238
#: netbox/ipam/filtersets.py:369 netbox/ipam/filtersets.py:989
#: netbox/extras/filtersets.py:531 netbox/ipam/filtersets.py:240
#: netbox/ipam/filtersets.py:371 netbox/ipam/filtersets.py:991
#: netbox/virtualization/filtersets.py:75
#: netbox/virtualization/filtersets.py:203 netbox/vpn/filtersets.py:363
msgid "Site (slug)"
@@ -277,13 +277,13 @@ msgstr "ASN"
#: netbox/circuits/filtersets.py:95 netbox/circuits/filtersets.py:122
#: netbox/circuits/filtersets.py:156 netbox/circuits/filtersets.py:283
#: netbox/circuits/filtersets.py:325 netbox/ipam/filtersets.py:243
#: netbox/circuits/filtersets.py:325 netbox/ipam/filtersets.py:245
msgid "Provider (ID)"
msgstr "Leverandør (ID)"
#: netbox/circuits/filtersets.py:101 netbox/circuits/filtersets.py:128
#: netbox/circuits/filtersets.py:162 netbox/circuits/filtersets.py:289
#: netbox/circuits/filtersets.py:331 netbox/ipam/filtersets.py:249
#: netbox/circuits/filtersets.py:331 netbox/ipam/filtersets.py:251
msgid "Provider (slug)"
msgstr "Leverandør (slug)"
@@ -312,8 +312,8 @@ msgstr "Kredsløbstype (slug)"
#: netbox/dcim/filtersets.py:452 netbox/dcim/filtersets.py:1045
#: netbox/dcim/filtersets.py:1393 netbox/dcim/filtersets.py:1928
#: netbox/dcim/filtersets.py:2170 netbox/dcim/filtersets.py:2229
#: netbox/ipam/filtersets.py:232 netbox/ipam/filtersets.py:363
#: netbox/ipam/filtersets.py:983 netbox/virtualization/filtersets.py:69
#: netbox/ipam/filtersets.py:234 netbox/ipam/filtersets.py:365
#: netbox/ipam/filtersets.py:985 netbox/virtualization/filtersets.py:69
#: netbox/virtualization/filtersets.py:197 netbox/vpn/filtersets.py:368
msgid "Site (ID)"
msgstr "Område (ID)"
@@ -667,7 +667,7 @@ msgstr "Leverandørkonto"
#: netbox/dcim/forms/filtersets.py:924 netbox/dcim/forms/filtersets.py:958
#: netbox/dcim/forms/filtersets.py:1059 netbox/dcim/forms/filtersets.py:1170
#: netbox/dcim/tables/devices.py:140 netbox/dcim/tables/devices.py:817
#: netbox/dcim/tables/devices.py:1063 netbox/dcim/tables/modules.py:69
#: netbox/dcim/tables/devices.py:1063 netbox/dcim/tables/modules.py:70
#: 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:256 netbox/ipam/forms/bulk_edit.py:306
@@ -1102,7 +1102,7 @@ msgstr "Opgave"
#: netbox/circuits/tables/circuits.py:155 netbox/dcim/forms/bulk_edit.py:118
#: 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:493
#: netbox/ipam/filtersets.py:1001 netbox/ipam/forms/bulk_edit.py:493
#: netbox/ipam/forms/bulk_import.py:460 netbox/ipam/forms/model_forms.py:561
#: netbox/ipam/tables/fhrp.py:67 netbox/ipam/tables/vlans.py:122
#: netbox/ipam/tables/vlans.py:226
@@ -1235,7 +1235,7 @@ msgstr "Kredsløbsgruppeopgaver"
#: netbox/circuits/models/circuits.py:240
msgid "termination"
msgstr "afslutning"
msgstr ""
#: netbox/circuits/models/circuits.py:257
msgid "port speed (Kbps)"
@@ -1297,15 +1297,11 @@ msgstr "kredsløbsafslutninger"
msgid ""
"A circuit termination must attach to either a site or a provider network."
msgstr ""
"En kredsløbsafslutning skal tilsluttes enten et område eller et "
"leverandørnetværk."
#: netbox/circuits/models/circuits.py:310
msgid ""
"A circuit termination cannot attach to both a site and a provider network."
msgstr ""
"En kredsløbsafslutning kan ikke knyttes til både et område og et "
"lerverandørnetværk."
#: netbox/circuits/models/providers.py:22
#: netbox/circuits/models/providers.py:66
@@ -1542,7 +1538,7 @@ msgstr "Forpligtelsesrate"
#: netbox/circuits/tables/providers.py:82
#: netbox/circuits/tables/providers.py:107 netbox/dcim/tables/devices.py:1036
#: 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:73 netbox/dcim/tables/power.py:39
#: netbox/dcim/tables/power.py:96 netbox/dcim/tables/racks.py:84
#: netbox/dcim/tables/racks.py:145 netbox/dcim/tables/racks.py:225
#: netbox/dcim/tables/sites.py:108 netbox/extras/tables/tables.py:582
@@ -2935,7 +2931,7 @@ msgid "Parent site group (slug)"
msgstr "Overordnet områdegruppe (slug)"
#: netbox/dcim/filtersets.py:164 netbox/extras/filtersets.py:364
#: netbox/ipam/filtersets.py:841 netbox/ipam/filtersets.py:993
#: netbox/ipam/filtersets.py:843 netbox/ipam/filtersets.py:995
msgid "Group (ID)"
msgstr "Gruppe (ID)"
@@ -2993,15 +2989,15 @@ msgstr "Racktype (ID)"
#: netbox/dcim/filtersets.py:411 netbox/dcim/filtersets.py:892
#: netbox/dcim/filtersets.py:994 netbox/dcim/filtersets.py:1850
#: netbox/ipam/filtersets.py:381 netbox/ipam/filtersets.py:493
#: netbox/ipam/filtersets.py:1003 netbox/virtualization/filtersets.py:210
#: netbox/ipam/filtersets.py:383 netbox/ipam/filtersets.py:495
#: netbox/ipam/filtersets.py:1005 netbox/virtualization/filtersets.py:210
msgid "Role (ID)"
msgstr "Rolle (ID)"
#: netbox/dcim/filtersets.py:417 netbox/dcim/filtersets.py:898
#: netbox/dcim/filtersets.py:1000 netbox/dcim/filtersets.py:1856
#: netbox/extras/filtersets.py:558 netbox/ipam/filtersets.py:387
#: netbox/ipam/filtersets.py:499 netbox/ipam/filtersets.py:1009
#: netbox/extras/filtersets.py:558 netbox/ipam/filtersets.py:389
#: netbox/ipam/filtersets.py:501 netbox/ipam/filtersets.py:1011
#: netbox/virtualization/filtersets.py:216
msgid "Role (slug)"
msgstr "Rolle (slug)"
@@ -3199,7 +3195,7 @@ msgstr "VDC (ID)"
msgid "Device model"
msgstr "Enhedsmodel"
#: netbox/dcim/filtersets.py:1267 netbox/ipam/filtersets.py:632
#: netbox/dcim/filtersets.py:1267 netbox/ipam/filtersets.py:634
#: netbox/vpn/filtersets.py:102 netbox/vpn/filtersets.py:401
msgid "Interface (ID)"
msgstr "Grænseflade (ID)"
@@ -3213,8 +3209,8 @@ msgid "Module bay (ID)"
msgstr "Modulplads (ID)"
#: netbox/dcim/filtersets.py:1333 netbox/dcim/filtersets.py:1425
#: netbox/ipam/filtersets.py:611 netbox/ipam/filtersets.py:851
#: netbox/ipam/filtersets.py:1115 netbox/virtualization/filtersets.py:161
#: netbox/ipam/filtersets.py:613 netbox/ipam/filtersets.py:853
#: netbox/ipam/filtersets.py:1117 netbox/virtualization/filtersets.py:161
#: netbox/vpn/filtersets.py:379
msgid "Device (ID)"
msgstr "Enhed (ID)"
@@ -3223,8 +3219,8 @@ msgstr "Enhed (ID)"
msgid "Rack (name)"
msgstr "Rack (navn)"
#: netbox/dcim/filtersets.py:1431 netbox/ipam/filtersets.py:606
#: netbox/ipam/filtersets.py:846 netbox/ipam/filtersets.py:1121
#: netbox/dcim/filtersets.py:1431 netbox/ipam/filtersets.py:608
#: netbox/ipam/filtersets.py:848 netbox/ipam/filtersets.py:1123
#: netbox/vpn/filtersets.py:374
msgid "Device (name)"
msgstr "Enhed (navn)"
@@ -3276,9 +3272,9 @@ msgstr "Tildelt VID"
#: netbox/dcim/forms/bulk_import.py:913 netbox/dcim/forms/filtersets.py:1428
#: netbox/dcim/forms/model_forms.py:1385
#: netbox/dcim/models/device_components.py:711
#: 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/dcim/tables/devices.py:626 netbox/ipam/filtersets.py:318
#: netbox/ipam/filtersets.py:329 netbox/ipam/filtersets.py:485
#: netbox/ipam/filtersets.py:586 netbox/ipam/filtersets.py:597
#: 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
@@ -3305,19 +3301,19 @@ msgstr "Tildelt VID"
msgid "VRF"
msgstr "VRF"
#: netbox/dcim/filtersets.py:1619 netbox/ipam/filtersets.py:322
#: netbox/ipam/filtersets.py:333 netbox/ipam/filtersets.py:489
#: netbox/ipam/filtersets.py:590 netbox/ipam/filtersets.py:601
#: netbox/dcim/filtersets.py:1619 netbox/ipam/filtersets.py:324
#: netbox/ipam/filtersets.py:335 netbox/ipam/filtersets.py:491
#: netbox/ipam/filtersets.py:592 netbox/ipam/filtersets.py:603
msgid "VRF (RD)"
msgstr "VRF (RED.)"
#: netbox/dcim/filtersets.py:1624 netbox/ipam/filtersets.py:1030
#: netbox/dcim/filtersets.py:1624 netbox/ipam/filtersets.py:1032
#: netbox/vpn/filtersets.py:342
msgid "L2VPN (ID)"
msgstr "L2VPN (ID)"
#: netbox/dcim/filtersets.py:1630 netbox/dcim/forms/filtersets.py:1433
#: netbox/dcim/tables/devices.py:570 netbox/ipam/filtersets.py:1036
#: netbox/dcim/tables/devices.py:570 netbox/ipam/filtersets.py:1038
#: netbox/ipam/forms/filtersets.py:518 netbox/ipam/tables/vlans.py:137
#: netbox/templates/dcim/interface.html:93 netbox/templates/ipam/vlan.html:66
#: netbox/templates/vpn/l2vpntermination.html:12
@@ -3479,7 +3475,7 @@ msgstr "Tidszone"
#: netbox/dcim/forms/object_import.py:187 netbox/dcim/tables/devices.py:96
#: netbox/dcim/tables/devices.py:172 netbox/dcim/tables/devices.py:940
#: netbox/dcim/tables/devicetypes.py:80 netbox/dcim/tables/devicetypes.py:308
#: netbox/dcim/tables/modules.py:20 netbox/dcim/tables/modules.py:60
#: netbox/dcim/tables/modules.py:20 netbox/dcim/tables/modules.py:61
#: netbox/dcim/tables/racks.py:58 netbox/dcim/tables/racks.py:132
#: netbox/templates/dcim/devicetype.html:14
#: netbox/templates/dcim/inventoryitem.html:44
@@ -3730,7 +3726,7 @@ msgid "Device Type"
msgstr "Enhedstype"
#: netbox/dcim/forms/bulk_edit.py:598 netbox/dcim/forms/model_forms.py:401
#: netbox/dcim/tables/modules.py:17 netbox/dcim/tables/modules.py:65
#: netbox/dcim/tables/modules.py:17 netbox/dcim/tables/modules.py:66
#: netbox/templates/dcim/module.html:65
#: netbox/templates/dcim/modulebay.html:66
#: netbox/templates/dcim/moduletype.html:22
@@ -3838,7 +3834,7 @@ msgstr "Klynge"
#: netbox/dcim/tables/devices.py:697 netbox/dcim/tables/devices.py:754
#: netbox/dcim/tables/devices.py:801 netbox/dcim/tables/devices.py:861
#: netbox/dcim/tables/devices.py:930 netbox/dcim/tables/devices.py:1057
#: netbox/dcim/tables/modules.py:52 netbox/extras/forms/filtersets.py:321
#: netbox/dcim/tables/modules.py:53 netbox/extras/forms/filtersets.py:321
#: netbox/ipam/forms/bulk_import.py:304 netbox/ipam/forms/bulk_import.py:505
#: netbox/ipam/forms/filtersets.py:551 netbox/ipam/forms/model_forms.py:323
#: netbox/ipam/forms/model_forms.py:712 netbox/ipam/forms/model_forms.py:745
@@ -4090,11 +4086,11 @@ msgstr "Mærkede VLAN'er"
#: netbox/dcim/forms/bulk_edit.py:1511
msgid "Add tagged VLANs"
msgstr ""
msgstr "Tilføj taggede VLAN'er"
#: netbox/dcim/forms/bulk_edit.py:1520
msgid "Remove tagged VLANs"
msgstr ""
msgstr "Fjern mærkede VLAN'er"
#: netbox/dcim/forms/bulk_edit.py:1536 netbox/dcim/forms/model_forms.py:1348
msgid "Wireless LAN group"
@@ -4142,7 +4138,7 @@ msgstr "802.1Q-skift"
#: netbox/dcim/forms/bulk_edit.py:1558
msgid "Add/Remove"
msgstr ""
msgstr "Tilføj/fjern"
#: netbox/dcim/forms/bulk_edit.py:1617 netbox/dcim/forms/bulk_edit.py:1619
msgid "Interface mode must be specified to assign VLANs"
@@ -4220,7 +4216,7 @@ msgstr "Navn på tildelt rolle"
#: netbox/dcim/forms/bulk_import.py:264
msgid "Rack type model"
msgstr ""
msgstr "Model af racktype"
#: netbox/dcim/forms/bulk_import.py:292 netbox/dcim/forms/bulk_import.py:435
#: netbox/dcim/forms/bulk_import.py:605
@@ -4229,11 +4225,11 @@ msgstr "Luftstrømsretning"
#: netbox/dcim/forms/bulk_import.py:324
msgid "Width must be set if not specifying a rack type."
msgstr ""
msgstr "Bredden skal indstilles, hvis der ikke angives en racktype."
#: netbox/dcim/forms/bulk_import.py:326
msgid "U height must be set if not specifying a rack type."
msgstr ""
msgstr "U-højde skal indstilles, hvis der ikke angives en racktype."
#: netbox/dcim/forms/bulk_import.py:334
msgid "Parent site"
@@ -4894,6 +4890,11 @@ msgid ""
"present, will be automatically replaced with the position value when "
"creating a new module."
msgstr ""
"Alfanumeriske intervaller understøttes til masseoprettelse. Blandede sager "
"og typer inden for et enkelt område understøttes ikke (eksempel: <code>[ge, "
"xe] -0/0/ [0-9]</code>). Tokenet <code>{module}</code>, hvis den er til "
"stede, erstattes automatisk med positionsværdien, når du opretter et nyt "
"modul."
#: netbox/dcim/forms/model_forms.py:1094
msgid "Console port template"
@@ -6782,7 +6783,7 @@ msgstr "Modulpladser"
msgid "Inventory items"
msgstr "Lagervarer"
#: netbox/dcim/tables/devices.py:305 netbox/dcim/tables/modules.py:56
#: netbox/dcim/tables/devices.py:305 netbox/dcim/tables/modules.py:57
#: netbox/templates/dcim/modulebay.html:17
msgid "Module Bay"
msgstr "Modulbugt"
@@ -7505,12 +7506,12 @@ msgstr "Bogmærker"
msgid "Show your personal bookmarks"
msgstr "Vis dine personlige bogmærker"
#: netbox/extras/events.py:147
#: netbox/extras/events.py:151
#, python-brace-format
msgid "Unknown action type for an event rule: {action_type}"
msgstr "Ukendt handlingstype for en hændelsesregel: {action_type}"
#: netbox/extras/events.py:192
#: netbox/extras/events.py:196
#, python-brace-format
msgid "Cannot import events pipeline {name} error: {error}"
msgstr "Kan ikke importere hændelsespipeline {name} fejl: {error}"
@@ -9268,129 +9269,129 @@ msgstr "Eksport af L2VPN"
msgid "Exporting L2VPN (identifier)"
msgstr "Eksport af L2VPN (identifikator)"
#: netbox/ipam/filtersets.py:155 netbox/ipam/filtersets.py:281
#: netbox/ipam/filtersets.py:155 netbox/ipam/filtersets.py:283
#: netbox/ipam/forms/model_forms.py:229 netbox/ipam/tables/ip.py:212
#: netbox/templates/ipam/prefix.html:12
msgid "Prefix"
msgstr "Præfiks"
#: netbox/ipam/filtersets.py:159 netbox/ipam/filtersets.py:198
#: netbox/ipam/filtersets.py:221
#: netbox/ipam/filtersets.py:223
msgid "RIR (ID)"
msgstr "RIR (ID)"
#: netbox/ipam/filtersets.py:165 netbox/ipam/filtersets.py:204
#: netbox/ipam/filtersets.py:227
#: netbox/ipam/filtersets.py:229
msgid "RIR (slug)"
msgstr "RIR (slug)"
#: netbox/ipam/filtersets.py:285
#: netbox/ipam/filtersets.py:287
msgid "Within prefix"
msgstr "Inden for præfiks"
#: netbox/ipam/filtersets.py:289
#: netbox/ipam/filtersets.py:291
msgid "Within and including prefix"
msgstr "Inden for og med præfiks"
#: netbox/ipam/filtersets.py:293
#: netbox/ipam/filtersets.py:295
msgid "Prefixes which contain this prefix or IP"
msgstr "Præfikser, der indeholder dette præfiks eller IP"
#: netbox/ipam/filtersets.py:304 netbox/ipam/filtersets.py:572
#: netbox/ipam/filtersets.py:306 netbox/ipam/filtersets.py:574
#: netbox/ipam/forms/bulk_edit.py:343 netbox/ipam/forms/filtersets.py:196
#: netbox/ipam/forms/filtersets.py:331
msgid "Mask length"
msgstr "Maskelængde"
#: netbox/ipam/filtersets.py:373 netbox/vpn/filtersets.py:427
#: netbox/ipam/filtersets.py:375 netbox/vpn/filtersets.py:427
msgid "VLAN (ID)"
msgstr "VLAN (ID)"
#: netbox/ipam/filtersets.py:377 netbox/vpn/filtersets.py:422
#: netbox/ipam/filtersets.py:379 netbox/vpn/filtersets.py:422
msgid "VLAN number (1-4094)"
msgstr "VLAN-nummer (1-4094)"
#: netbox/ipam/filtersets.py:471 netbox/ipam/filtersets.py:475
#: netbox/ipam/filtersets.py:567 netbox/ipam/forms/model_forms.py:496
#: netbox/ipam/filtersets.py:473 netbox/ipam/filtersets.py:477
#: netbox/ipam/filtersets.py:569 netbox/ipam/forms/model_forms.py:496
#: netbox/templates/tenancy/contact.html:53
#: netbox/tenancy/forms/bulk_edit.py:113
msgid "Address"
msgstr "Adresse"
#: netbox/ipam/filtersets.py:479
#: netbox/ipam/filtersets.py:481
msgid "Ranges which contain this prefix or IP"
msgstr "Intervaller, der indeholder dette præfiks eller IP"
#: netbox/ipam/filtersets.py:507 netbox/ipam/filtersets.py:563
#: netbox/ipam/filtersets.py:509 netbox/ipam/filtersets.py:565
msgid "Parent prefix"
msgstr "Forældrepræfiks"
#: netbox/ipam/filtersets.py:616 netbox/ipam/filtersets.py:856
#: netbox/ipam/filtersets.py:1131 netbox/vpn/filtersets.py:385
#: netbox/ipam/filtersets.py:618 netbox/ipam/filtersets.py:858
#: netbox/ipam/filtersets.py:1133 netbox/vpn/filtersets.py:385
msgid "Virtual machine (name)"
msgstr "Virtuel maskine (navn)"
#: netbox/ipam/filtersets.py:621 netbox/ipam/filtersets.py:861
#: netbox/ipam/filtersets.py:1125 netbox/virtualization/filtersets.py:282
#: netbox/ipam/filtersets.py:623 netbox/ipam/filtersets.py:863
#: netbox/ipam/filtersets.py:1127 netbox/virtualization/filtersets.py:282
#: netbox/virtualization/filtersets.py:321 netbox/vpn/filtersets.py:390
msgid "Virtual machine (ID)"
msgstr "Virtuel maskine (ID)"
#: netbox/ipam/filtersets.py:627 netbox/vpn/filtersets.py:97
#: netbox/ipam/filtersets.py:629 netbox/vpn/filtersets.py:97
#: netbox/vpn/filtersets.py:396
msgid "Interface (name)"
msgstr "Grænseflade (navn)"
#: netbox/ipam/filtersets.py:638 netbox/vpn/filtersets.py:108
#: netbox/ipam/filtersets.py:640 netbox/vpn/filtersets.py:108
#: netbox/vpn/filtersets.py:407
msgid "VM interface (name)"
msgstr "VM-grænseflade (navn)"
#: netbox/ipam/filtersets.py:643 netbox/vpn/filtersets.py:113
#: netbox/ipam/filtersets.py:645 netbox/vpn/filtersets.py:113
msgid "VM interface (ID)"
msgstr "VM-grænseflade (ID)"
#: netbox/ipam/filtersets.py:648
#: netbox/ipam/filtersets.py:650
msgid "FHRP group (ID)"
msgstr "FHRP-gruppe (ID)"
#: netbox/ipam/filtersets.py:652
#: netbox/ipam/filtersets.py:654
msgid "Is assigned to an interface"
msgstr "Tildeles til en grænseflade"
#: netbox/ipam/filtersets.py:656
#: netbox/ipam/filtersets.py:658
msgid "Is assigned"
msgstr "Er tildelt"
#: netbox/ipam/filtersets.py:668
#: netbox/ipam/filtersets.py:670
msgid "Service (ID)"
msgstr "Tjeneste (ID)"
#: netbox/ipam/filtersets.py:673
#: netbox/ipam/filtersets.py:675
msgid "NAT inside IP address (ID)"
msgstr "NAT inde i IP-adresse (ID)"
#: netbox/ipam/filtersets.py:1041 netbox/ipam/forms/bulk_import.py:322
#: netbox/ipam/filtersets.py:1043 netbox/ipam/forms/bulk_import.py:322
msgid "Assigned interface"
msgstr "Tildelt grænseflade"
#: netbox/ipam/filtersets.py:1046
#: netbox/ipam/filtersets.py:1048
msgid "Assigned VM interface"
msgstr "Tildelt VM grænseflade"
#: netbox/ipam/filtersets.py:1136
#: netbox/ipam/filtersets.py:1138
msgid "IP address (ID)"
msgstr "IP-adresse (ID)"
#: netbox/ipam/filtersets.py:1142 netbox/ipam/models/ip.py:788
#: netbox/ipam/filtersets.py:1144 netbox/ipam/models/ip.py:788
msgid "IP address"
msgstr "IP adresse"
#: netbox/ipam/filtersets.py:1167
#: netbox/ipam/filtersets.py:1169
msgid "Primary IPv4 (ID)"
msgstr "Primær IPv4 (ID)"
#: netbox/ipam/filtersets.py:1172
#: netbox/ipam/filtersets.py:1174
msgid "Primary IPv6 (ID)"
msgstr "Primær IPv6 (ID)"
@@ -9614,11 +9615,11 @@ msgstr "Gør dette til den primære IP for den tildelte enhed"
#: netbox/ipam/forms/bulk_import.py:330
msgid "Is out-of-band"
msgstr ""
msgstr "Er uden for båndet"
#: netbox/ipam/forms/bulk_import.py:331
msgid "Designate this as the out-of-band IP address for the assigned device"
msgstr ""
msgstr "Angiv dette som IP-adressen uden for båndet for den tildelte enhed"
#: netbox/ipam/forms/bulk_import.py:371
msgid "No device or virtual machine specified; cannot set as primary IP"
@@ -9627,11 +9628,11 @@ msgstr ""
#: netbox/ipam/forms/bulk_import.py:375
msgid "No device specified; cannot set as out-of-band IP"
msgstr ""
msgstr "Ingen enhed angivet; kan ikke indstilles som IP uden for båndet"
#: netbox/ipam/forms/bulk_import.py:379
msgid "Cannot set out-of-band IP for virtual machines"
msgstr ""
msgstr "Kan ikke angive IP uden for båndet til virtuelle maskiner"
#: netbox/ipam/forms/bulk_import.py:383
msgid "No interface specified; cannot set as primary IP"
@@ -9639,7 +9640,7 @@ msgstr "Ingen grænseflade angivet; kan ikke indstilles som primær IP"
#: netbox/ipam/forms/bulk_import.py:387
msgid "No interface specified; cannot set as out-of-band IP"
msgstr ""
msgstr "Ingen grænseflade angivet; kan ikke indstilles som IP uden for båndet"
#: netbox/ipam/forms/bulk_import.py:422
msgid "Auth type"
@@ -9798,7 +9799,7 @@ msgstr "ASN-rækkevidde"
#: netbox/ipam/forms/model_forms.py:231
msgid "Site/VLAN Assignment"
msgstr "Område/VLAN-tildeling"
msgstr ""
#: netbox/ipam/forms/model_forms.py:259 netbox/templates/ipam/iprange.html:10
msgid "IP Range"
@@ -9816,7 +9817,7 @@ msgstr "Gør dette til den primære IP for enheden/VM"
#: netbox/ipam/forms/model_forms.py:314
msgid "Make this the out-of-band IP for the device"
msgstr ""
msgstr "Gør dette til enhedens off-band IP"
#: netbox/ipam/forms/model_forms.py:329
msgid "NAT IP (Inside)"
@@ -9828,11 +9829,13 @@ msgstr "En IP-adresse kan kun tildeles et enkelt objekt."
#: netbox/ipam/forms/model_forms.py:398
msgid "Cannot reassign primary IP address for the parent device/VM"
msgstr ""
msgstr "Kan ikke omtildele primær IP-adresse til den overordnede enhed/VM"
#: netbox/ipam/forms/model_forms.py:402
msgid "Cannot reassign out-of-Band IP address for the parent device"
msgstr ""
"Det er ikke muligt at omfordele IP-adressen uden for båndet til den "
"overordnede enhed"
#: netbox/ipam/forms/model_forms.py:412
msgid ""
@@ -9846,6 +9849,8 @@ msgid ""
"Only IP addresses assigned to a device interface can be designated as the "
"out-of-band IP for a device."
msgstr ""
"Kun IP-adresser, der er tildelt en enhedsgrænseflade, kan betegnes som en "
"enheds off-band IP."
#: netbox/ipam/forms/model_forms.py:508
msgid "Virtual IP Address"
@@ -10245,11 +10250,15 @@ msgstr "Kan ikke indstille scope_id uden scope_type."
#, python-brace-format
msgid "Starting VLAN ID in range ({value}) cannot be less than {minimum}"
msgstr ""
"Start af VLAN-ID inden for rækkevidde ({value}) kan ikke være mindre end "
"{minimum}"
#: netbox/ipam/models/vlans.py:111
#, python-brace-format
msgid "Ending VLAN ID in range ({value}) cannot exceed {maximum}"
msgstr ""
"Afslutning af VLAN-ID inden for rækkevidde ({value}) kan ikke overstige "
"{maximum}"
#: netbox/ipam/models/vlans.py:118
#, python-brace-format
@@ -10257,6 +10266,8 @@ msgid ""
"Ending VLAN ID in range must be greater than or equal to the starting VLAN "
"ID ({range})"
msgstr ""
"Afsluttende VLAN-id inden for rækkevidde skal være større end eller lig med "
"det startende VLAN-id ({range})"
#: netbox/ipam/models/vlans.py:124
msgid "Ranges cannot overlap."
@@ -12616,7 +12627,7 @@ msgstr "Hent"
#: netbox/templates/dcim/device/render_config.html:64
#: netbox/templates/virtualization/virtualmachine/render_config.html:64
msgid "Error rendering template"
msgstr ""
msgstr "Fejl ved gengivelse af skabelon"
#: netbox/templates/dcim/device/render_config.html:70
msgid "No configuration template has been assigned for this device."
@@ -13488,7 +13499,7 @@ msgstr "Kør igen"
#: netbox/templates/extras/script_list.html:133
#, python-format
msgid "Could not load scripts from module %(module)s"
msgstr ""
msgstr "Kunne ikke indlæse scripts fra modulet %(module)s"
#: netbox/templates/extras/script_list.html:141
msgid "No Scripts Found"
@@ -13888,7 +13899,7 @@ msgstr "Hjælpecenter"
#: netbox/templates/inc/user_menu.html:41
msgid "Django Admin"
msgstr "Django Admin"
msgstr ""
#: netbox/templates/inc/user_menu.html:61
msgid "Log Out"
@@ -15371,12 +15382,12 @@ msgstr "Hukommelse (MB)"
#: netbox/virtualization/forms/bulk_edit.py:174
msgid "Disk (MB)"
msgstr ""
msgstr "Disk (MB)"
#: netbox/virtualization/forms/bulk_edit.py:334
#: netbox/virtualization/forms/filtersets.py:251
msgid "Size (MB)"
msgstr ""
msgstr "Størrelse (MB)"
#: netbox/virtualization/forms/bulk_import.py:44
msgid "Type of cluster"
@@ -15404,8 +15415,6 @@ msgid ""
"{device} belongs to a different site ({device_site}) than the cluster "
"({cluster_site})"
msgstr ""
"{device} tilhører et andet område ({device_site}) end cluster "
"({cluster_site})"
#: netbox/virtualization/forms/model_forms.py:192
msgid "Optionally pin this VM to a specific host device within the cluster"
@@ -15583,19 +15592,19 @@ msgstr "GREE"
#: netbox/vpn/choices.py:39
msgid "WireGuard"
msgstr ""
msgstr "WireGuard"
#: netbox/vpn/choices.py:40
msgid "OpenVPN"
msgstr ""
msgstr "OpenVPN"
#: netbox/vpn/choices.py:41
msgid "L2TP"
msgstr ""
msgstr "L2TP"
#: netbox/vpn/choices.py:42
msgid "PPTP"
msgstr ""
msgstr "PPTP"
#: netbox/vpn/choices.py:64
msgid "Hub"
@@ -16135,7 +16144,7 @@ msgstr "trådløse links"
#: netbox/wireless/models.py:236
msgid "Must specify a unit when setting a wireless distance"
msgstr "Skal angive en enhed, når du indstiller en trådløs afstand"
msgstr ""
#: netbox/wireless/models.py:242 netbox/wireless/models.py:248
#, python-brace-format

View File

@@ -5,22 +5,22 @@
#
# Translators:
# Martin R, 2024
# Niklas, 2024
# fepilins, 2024
# Steffen, 2024
# haagehan, 2024
# Jeremy Stretch, 2024
# Robin Reinhardt, 2024
# chbally, 2024
# chbally, 2025
# Niklas, 2025
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-12-12 05:02+0000\n"
"POT-Creation-Date: 2025-01-04 05:02+0000\n"
"PO-Revision-Date: 2023-10-30 17:48+0000\n"
"Last-Translator: chbally, 2024\n"
"Last-Translator: Niklas, 2025\n"
"Language-Team: German (https://app.transifex.com/netbox-community/teams/178115/de/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@@ -157,7 +157,7 @@ msgstr "Inaktiv"
#: netbox/dcim/filtersets.py:464 netbox/dcim/filtersets.py:1021
#: netbox/dcim/filtersets.py:1368 netbox/dcim/filtersets.py:1903
#: netbox/dcim/filtersets.py:2146 netbox/dcim/filtersets.py:2204
#: netbox/ipam/filtersets.py:339 netbox/ipam/filtersets.py:959
#: netbox/ipam/filtersets.py:341 netbox/ipam/filtersets.py:961
#: netbox/virtualization/filtersets.py:45
#: netbox/virtualization/filtersets.py:173 netbox/vpn/filtersets.py:358
msgid "Region (ID)"
@@ -169,8 +169,8 @@ msgstr "Region (ID)"
#: netbox/dcim/filtersets.py:471 netbox/dcim/filtersets.py:1028
#: netbox/dcim/filtersets.py:1375 netbox/dcim/filtersets.py:1910
#: netbox/dcim/filtersets.py:2153 netbox/dcim/filtersets.py:2211
#: netbox/extras/filtersets.py:509 netbox/ipam/filtersets.py:346
#: netbox/ipam/filtersets.py:966 netbox/virtualization/filtersets.py:52
#: netbox/extras/filtersets.py:509 netbox/ipam/filtersets.py:348
#: netbox/ipam/filtersets.py:968 netbox/virtualization/filtersets.py:52
#: netbox/virtualization/filtersets.py:180 netbox/vpn/filtersets.py:353
msgid "Region (slug)"
msgstr "Region (URL-Slug)"
@@ -180,8 +180,8 @@ msgstr "Region (URL-Slug)"
#: netbox/dcim/filtersets.py:346 netbox/dcim/filtersets.py:477
#: netbox/dcim/filtersets.py:1034 netbox/dcim/filtersets.py:1381
#: netbox/dcim/filtersets.py:1916 netbox/dcim/filtersets.py:2159
#: netbox/dcim/filtersets.py:2217 netbox/ipam/filtersets.py:352
#: netbox/ipam/filtersets.py:972 netbox/virtualization/filtersets.py:58
#: netbox/dcim/filtersets.py:2217 netbox/ipam/filtersets.py:354
#: netbox/ipam/filtersets.py:974 netbox/virtualization/filtersets.py:58
#: netbox/virtualization/filtersets.py:186
msgid "Site group (ID)"
msgstr "Standortgruppe (ID)"
@@ -192,7 +192,7 @@ msgstr "Standortgruppe (ID)"
#: netbox/dcim/filtersets.py:1041 netbox/dcim/filtersets.py:1388
#: netbox/dcim/filtersets.py:1923 netbox/dcim/filtersets.py:2166
#: netbox/dcim/filtersets.py:2224 netbox/extras/filtersets.py:515
#: netbox/ipam/filtersets.py:359 netbox/ipam/filtersets.py:979
#: netbox/ipam/filtersets.py:361 netbox/ipam/filtersets.py:981
#: netbox/virtualization/filtersets.py:65
#: netbox/virtualization/filtersets.py:193
msgid "Site group (slug)"
@@ -262,8 +262,8 @@ msgstr "Standort"
#: netbox/circuits/filtersets.py:62 netbox/circuits/filtersets.py:229
#: netbox/circuits/filtersets.py:274 netbox/dcim/filtersets.py:242
#: netbox/dcim/filtersets.py:363 netbox/dcim/filtersets.py:458
#: netbox/extras/filtersets.py:531 netbox/ipam/filtersets.py:238
#: netbox/ipam/filtersets.py:369 netbox/ipam/filtersets.py:989
#: netbox/extras/filtersets.py:531 netbox/ipam/filtersets.py:240
#: netbox/ipam/filtersets.py:371 netbox/ipam/filtersets.py:991
#: netbox/virtualization/filtersets.py:75
#: netbox/virtualization/filtersets.py:203 netbox/vpn/filtersets.py:363
msgid "Site (slug)"
@@ -282,13 +282,13 @@ msgstr "ASN"
#: netbox/circuits/filtersets.py:95 netbox/circuits/filtersets.py:122
#: netbox/circuits/filtersets.py:156 netbox/circuits/filtersets.py:283
#: netbox/circuits/filtersets.py:325 netbox/ipam/filtersets.py:243
#: netbox/circuits/filtersets.py:325 netbox/ipam/filtersets.py:245
msgid "Provider (ID)"
msgstr "Provider (ID)"
#: netbox/circuits/filtersets.py:101 netbox/circuits/filtersets.py:128
#: netbox/circuits/filtersets.py:162 netbox/circuits/filtersets.py:289
#: netbox/circuits/filtersets.py:331 netbox/ipam/filtersets.py:249
#: netbox/circuits/filtersets.py:331 netbox/ipam/filtersets.py:251
msgid "Provider (slug)"
msgstr "Provider (URL-Slug)"
@@ -317,8 +317,8 @@ msgstr "Transportnetz Typ (URL-Slug)"
#: netbox/dcim/filtersets.py:452 netbox/dcim/filtersets.py:1045
#: netbox/dcim/filtersets.py:1393 netbox/dcim/filtersets.py:1928
#: netbox/dcim/filtersets.py:2170 netbox/dcim/filtersets.py:2229
#: netbox/ipam/filtersets.py:232 netbox/ipam/filtersets.py:363
#: netbox/ipam/filtersets.py:983 netbox/virtualization/filtersets.py:69
#: netbox/ipam/filtersets.py:234 netbox/ipam/filtersets.py:365
#: netbox/ipam/filtersets.py:985 netbox/virtualization/filtersets.py:69
#: netbox/virtualization/filtersets.py:197 netbox/vpn/filtersets.py:368
msgid "Site (ID)"
msgstr "Standort (ID)"
@@ -672,7 +672,7 @@ msgstr "Providerkonto"
#: netbox/dcim/forms/filtersets.py:924 netbox/dcim/forms/filtersets.py:958
#: netbox/dcim/forms/filtersets.py:1059 netbox/dcim/forms/filtersets.py:1170
#: netbox/dcim/tables/devices.py:140 netbox/dcim/tables/devices.py:817
#: netbox/dcim/tables/devices.py:1063 netbox/dcim/tables/modules.py:69
#: netbox/dcim/tables/devices.py:1063 netbox/dcim/tables/modules.py:70
#: 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:256 netbox/ipam/forms/bulk_edit.py:306
@@ -1107,7 +1107,7 @@ msgstr "Zuweisung"
#: netbox/circuits/tables/circuits.py:155 netbox/dcim/forms/bulk_edit.py:118
#: 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:493
#: netbox/ipam/filtersets.py:1001 netbox/ipam/forms/bulk_edit.py:493
#: netbox/ipam/forms/bulk_import.py:460 netbox/ipam/forms/model_forms.py:561
#: netbox/ipam/tables/fhrp.py:67 netbox/ipam/tables/vlans.py:122
#: netbox/ipam/tables/vlans.py:226
@@ -1240,7 +1240,7 @@ msgstr "Transportnetzzuweisungen"
#: netbox/circuits/models/circuits.py:240
msgid "termination"
msgstr "Abschlusspunkt"
msgstr ""
#: netbox/circuits/models/circuits.py:257
msgid "port speed (Kbps)"
@@ -1303,15 +1303,11 @@ msgstr "Transportnetzabschlusspunkte"
msgid ""
"A circuit termination must attach to either a site or a provider network."
msgstr ""
"Ein Leitungsabschluss muss entweder an einen Standort oder an ein "
"Providernetzwerk angeschlossen werden."
#: netbox/circuits/models/circuits.py:310
msgid ""
"A circuit termination cannot attach to both a site and a provider network."
msgstr ""
"Ein Leitungsabschluss kann nicht sowohl an einen Standort als auch an ein "
"Providernetzwerk angeschlossen werden."
#: netbox/circuits/models/providers.py:22
#: netbox/circuits/models/providers.py:66
@@ -1548,7 +1544,7 @@ msgstr "Garantierte Bandbreite"
#: netbox/circuits/tables/providers.py:82
#: netbox/circuits/tables/providers.py:107 netbox/dcim/tables/devices.py:1036
#: 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:73 netbox/dcim/tables/power.py:39
#: netbox/dcim/tables/power.py:96 netbox/dcim/tables/racks.py:84
#: netbox/dcim/tables/racks.py:145 netbox/dcim/tables/racks.py:225
#: netbox/dcim/tables/sites.py:108 netbox/extras/tables/tables.py:582
@@ -2951,7 +2947,7 @@ msgid "Parent site group (slug)"
msgstr "Übergeordnete Standortgruppe (URL-Slug)"
#: netbox/dcim/filtersets.py:164 netbox/extras/filtersets.py:364
#: netbox/ipam/filtersets.py:841 netbox/ipam/filtersets.py:993
#: netbox/ipam/filtersets.py:843 netbox/ipam/filtersets.py:995
msgid "Group (ID)"
msgstr "Gruppe (ID)"
@@ -3009,15 +3005,15 @@ msgstr "Racktyp (ID)"
#: netbox/dcim/filtersets.py:411 netbox/dcim/filtersets.py:892
#: netbox/dcim/filtersets.py:994 netbox/dcim/filtersets.py:1850
#: netbox/ipam/filtersets.py:381 netbox/ipam/filtersets.py:493
#: netbox/ipam/filtersets.py:1003 netbox/virtualization/filtersets.py:210
#: netbox/ipam/filtersets.py:383 netbox/ipam/filtersets.py:495
#: netbox/ipam/filtersets.py:1005 netbox/virtualization/filtersets.py:210
msgid "Role (ID)"
msgstr "Rolle (ID)"
#: netbox/dcim/filtersets.py:417 netbox/dcim/filtersets.py:898
#: netbox/dcim/filtersets.py:1000 netbox/dcim/filtersets.py:1856
#: netbox/extras/filtersets.py:558 netbox/ipam/filtersets.py:387
#: netbox/ipam/filtersets.py:499 netbox/ipam/filtersets.py:1009
#: netbox/extras/filtersets.py:558 netbox/ipam/filtersets.py:389
#: netbox/ipam/filtersets.py:501 netbox/ipam/filtersets.py:1011
#: netbox/virtualization/filtersets.py:216
msgid "Role (slug)"
msgstr "Rolle (URL-Slug)"
@@ -3215,7 +3211,7 @@ msgstr "VDC (ID)"
msgid "Device model"
msgstr "Modell des Geräts"
#: netbox/dcim/filtersets.py:1267 netbox/ipam/filtersets.py:632
#: netbox/dcim/filtersets.py:1267 netbox/ipam/filtersets.py:634
#: netbox/vpn/filtersets.py:102 netbox/vpn/filtersets.py:401
msgid "Interface (ID)"
msgstr "Schnittstelle (ID)"
@@ -3229,8 +3225,8 @@ msgid "Module bay (ID)"
msgstr "Modulschacht (ID)"
#: netbox/dcim/filtersets.py:1333 netbox/dcim/filtersets.py:1425
#: netbox/ipam/filtersets.py:611 netbox/ipam/filtersets.py:851
#: netbox/ipam/filtersets.py:1115 netbox/virtualization/filtersets.py:161
#: netbox/ipam/filtersets.py:613 netbox/ipam/filtersets.py:853
#: netbox/ipam/filtersets.py:1117 netbox/virtualization/filtersets.py:161
#: netbox/vpn/filtersets.py:379
msgid "Device (ID)"
msgstr "Gerät (ID)"
@@ -3239,8 +3235,8 @@ msgstr "Gerät (ID)"
msgid "Rack (name)"
msgstr "Rack (Name)"
#: netbox/dcim/filtersets.py:1431 netbox/ipam/filtersets.py:606
#: netbox/ipam/filtersets.py:846 netbox/ipam/filtersets.py:1121
#: netbox/dcim/filtersets.py:1431 netbox/ipam/filtersets.py:608
#: netbox/ipam/filtersets.py:848 netbox/ipam/filtersets.py:1123
#: netbox/vpn/filtersets.py:374
msgid "Device (name)"
msgstr "Gerät (Name)"
@@ -3292,9 +3288,9 @@ msgstr "Zugewiesene VID"
#: netbox/dcim/forms/bulk_import.py:913 netbox/dcim/forms/filtersets.py:1428
#: netbox/dcim/forms/model_forms.py:1385
#: netbox/dcim/models/device_components.py:711
#: 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/dcim/tables/devices.py:626 netbox/ipam/filtersets.py:318
#: netbox/ipam/filtersets.py:329 netbox/ipam/filtersets.py:485
#: netbox/ipam/filtersets.py:586 netbox/ipam/filtersets.py:597
#: 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
@@ -3321,19 +3317,19 @@ msgstr "Zugewiesene VID"
msgid "VRF"
msgstr "VRF"
#: netbox/dcim/filtersets.py:1619 netbox/ipam/filtersets.py:322
#: netbox/ipam/filtersets.py:333 netbox/ipam/filtersets.py:489
#: netbox/ipam/filtersets.py:590 netbox/ipam/filtersets.py:601
#: netbox/dcim/filtersets.py:1619 netbox/ipam/filtersets.py:324
#: netbox/ipam/filtersets.py:335 netbox/ipam/filtersets.py:491
#: netbox/ipam/filtersets.py:592 netbox/ipam/filtersets.py:603
msgid "VRF (RD)"
msgstr "VRF (RD)"
#: netbox/dcim/filtersets.py:1624 netbox/ipam/filtersets.py:1030
#: netbox/dcim/filtersets.py:1624 netbox/ipam/filtersets.py:1032
#: netbox/vpn/filtersets.py:342
msgid "L2VPN (ID)"
msgstr "L2VPN (ID)"
#: netbox/dcim/filtersets.py:1630 netbox/dcim/forms/filtersets.py:1433
#: netbox/dcim/tables/devices.py:570 netbox/ipam/filtersets.py:1036
#: netbox/dcim/tables/devices.py:570 netbox/ipam/filtersets.py:1038
#: netbox/ipam/forms/filtersets.py:518 netbox/ipam/tables/vlans.py:137
#: netbox/templates/dcim/interface.html:93 netbox/templates/ipam/vlan.html:66
#: netbox/templates/vpn/l2vpntermination.html:12
@@ -3495,7 +3491,7 @@ msgstr "Zeitzone"
#: netbox/dcim/forms/object_import.py:187 netbox/dcim/tables/devices.py:96
#: netbox/dcim/tables/devices.py:172 netbox/dcim/tables/devices.py:940
#: netbox/dcim/tables/devicetypes.py:80 netbox/dcim/tables/devicetypes.py:308
#: netbox/dcim/tables/modules.py:20 netbox/dcim/tables/modules.py:60
#: netbox/dcim/tables/modules.py:20 netbox/dcim/tables/modules.py:61
#: netbox/dcim/tables/racks.py:58 netbox/dcim/tables/racks.py:132
#: netbox/templates/dcim/devicetype.html:14
#: netbox/templates/dcim/inventoryitem.html:44
@@ -3746,7 +3742,7 @@ msgid "Device Type"
msgstr "Gerätetyp"
#: netbox/dcim/forms/bulk_edit.py:598 netbox/dcim/forms/model_forms.py:401
#: netbox/dcim/tables/modules.py:17 netbox/dcim/tables/modules.py:65
#: netbox/dcim/tables/modules.py:17 netbox/dcim/tables/modules.py:66
#: netbox/templates/dcim/module.html:65
#: netbox/templates/dcim/modulebay.html:66
#: netbox/templates/dcim/moduletype.html:22
@@ -3854,7 +3850,7 @@ msgstr "Cluster"
#: netbox/dcim/tables/devices.py:697 netbox/dcim/tables/devices.py:754
#: netbox/dcim/tables/devices.py:801 netbox/dcim/tables/devices.py:861
#: netbox/dcim/tables/devices.py:930 netbox/dcim/tables/devices.py:1057
#: netbox/dcim/tables/modules.py:52 netbox/extras/forms/filtersets.py:321
#: netbox/dcim/tables/modules.py:53 netbox/extras/forms/filtersets.py:321
#: netbox/ipam/forms/bulk_import.py:304 netbox/ipam/forms/bulk_import.py:505
#: netbox/ipam/forms/filtersets.py:551 netbox/ipam/forms/model_forms.py:323
#: netbox/ipam/forms/model_forms.py:712 netbox/ipam/forms/model_forms.py:745
@@ -4589,7 +4585,7 @@ msgstr ""
#: netbox/dcim/forms/bulk_import.py:1290
#, python-brace-format
msgid "{side_upper} side termination not found: {device} {name}"
msgstr "{side_upper} Seitlicher Abschluss nicht gefunden: {device} {name}"
msgstr "{side_upper} Standort Abschluss nicht gefunden: {device} {name}"
#: netbox/dcim/forms/bulk_import.py:1315 netbox/dcim/forms/model_forms.py:785
#: netbox/dcim/tables/devices.py:1027 netbox/templates/dcim/device.html:132
@@ -4682,7 +4678,7 @@ msgstr ""
#, python-brace-format
msgid "Cannot adopt {model} {name} as it already belongs to a module"
msgstr ""
"Kann nicht adoptieren {model} {name} da es schon zu einem Modul gehört"
"Kann nicht {model} {name} aufnehmenm, da es schon zu einem Modul gehört"
#: netbox/dcim/forms/common.py:153
#, python-brace-format
@@ -6888,7 +6884,7 @@ msgstr "Moduleinsätze"
msgid "Inventory items"
msgstr "Inventarartikel"
#: netbox/dcim/tables/devices.py:305 netbox/dcim/tables/modules.py:56
#: netbox/dcim/tables/devices.py:305 netbox/dcim/tables/modules.py:57
#: netbox/templates/dcim/modulebay.html:17
msgid "Module Bay"
msgstr "Moduleinsatz"
@@ -7619,12 +7615,12 @@ msgstr "Lesezeichen"
msgid "Show your personal bookmarks"
msgstr "Zeige persönliche Lesezeichen an"
#: netbox/extras/events.py:147
#: netbox/extras/events.py:151
#, python-brace-format
msgid "Unknown action type for an event rule: {action_type}"
msgstr "Unbekannter Aktionstyp für eine Ereignisregel: {action_type}"
#: netbox/extras/events.py:192
#: netbox/extras/events.py:196
#, python-brace-format
msgid "Cannot import events pipeline {name} error: {error}"
msgstr "Ereignispipeline kann nicht importiert werden {name} Fehler: {error}"
@@ -8438,8 +8434,7 @@ msgstr "Gewicht anzeigen"
#: netbox/extras/models/customfields.py:173
msgid "Fields with higher weights appear lower in a form."
msgstr ""
"Felder mit höheren Gewichten werden in einem Formular niedriger angezeigt."
msgstr "Höher gewichtete Felder werden im Formular weiter unten angezeigt."
#: netbox/extras/models/customfields.py:178
msgid "minimum value"
@@ -9431,129 +9426,129 @@ msgstr "L2VPN exportieren"
msgid "Exporting L2VPN (identifier)"
msgstr "L2VPN exportieren (Identifier)"
#: netbox/ipam/filtersets.py:155 netbox/ipam/filtersets.py:281
#: netbox/ipam/filtersets.py:155 netbox/ipam/filtersets.py:283
#: netbox/ipam/forms/model_forms.py:229 netbox/ipam/tables/ip.py:212
#: netbox/templates/ipam/prefix.html:12
msgid "Prefix"
msgstr "Prefix"
#: netbox/ipam/filtersets.py:159 netbox/ipam/filtersets.py:198
#: netbox/ipam/filtersets.py:221
#: netbox/ipam/filtersets.py:223
msgid "RIR (ID)"
msgstr "RIR (ID)"
#: netbox/ipam/filtersets.py:165 netbox/ipam/filtersets.py:204
#: netbox/ipam/filtersets.py:227
#: netbox/ipam/filtersets.py:229
msgid "RIR (slug)"
msgstr "RIR (URL-Slug)"
#: netbox/ipam/filtersets.py:285
#: netbox/ipam/filtersets.py:287
msgid "Within prefix"
msgstr "Innerhalb des Prefixes"
#: netbox/ipam/filtersets.py:289
#: netbox/ipam/filtersets.py:291
msgid "Within and including prefix"
msgstr "Innerhalb und einschließlich Präfix"
#: netbox/ipam/filtersets.py:293
#: netbox/ipam/filtersets.py:295
msgid "Prefixes which contain this prefix or IP"
msgstr "Präfixe, die dieses Präfix oder diese IP enthalten"
#: netbox/ipam/filtersets.py:304 netbox/ipam/filtersets.py:572
#: netbox/ipam/filtersets.py:306 netbox/ipam/filtersets.py:574
#: netbox/ipam/forms/bulk_edit.py:343 netbox/ipam/forms/filtersets.py:196
#: netbox/ipam/forms/filtersets.py:331
msgid "Mask length"
msgstr "Länge der Maske"
#: netbox/ipam/filtersets.py:373 netbox/vpn/filtersets.py:427
#: netbox/ipam/filtersets.py:375 netbox/vpn/filtersets.py:427
msgid "VLAN (ID)"
msgstr "VLAN (ID)"
#: netbox/ipam/filtersets.py:377 netbox/vpn/filtersets.py:422
#: netbox/ipam/filtersets.py:379 netbox/vpn/filtersets.py:422
msgid "VLAN number (1-4094)"
msgstr "VLAN-Nummer (1-4094)"
#: netbox/ipam/filtersets.py:471 netbox/ipam/filtersets.py:475
#: netbox/ipam/filtersets.py:567 netbox/ipam/forms/model_forms.py:496
#: netbox/ipam/filtersets.py:473 netbox/ipam/filtersets.py:477
#: netbox/ipam/filtersets.py:569 netbox/ipam/forms/model_forms.py:496
#: netbox/templates/tenancy/contact.html:53
#: netbox/tenancy/forms/bulk_edit.py:113
msgid "Address"
msgstr "Adresse"
#: netbox/ipam/filtersets.py:479
#: netbox/ipam/filtersets.py:481
msgid "Ranges which contain this prefix or IP"
msgstr "Bereiche, die dieses Präfix oder diese IP enthalten"
#: netbox/ipam/filtersets.py:507 netbox/ipam/filtersets.py:563
#: netbox/ipam/filtersets.py:509 netbox/ipam/filtersets.py:565
msgid "Parent prefix"
msgstr "Übergeordnetes Präfix"
#: netbox/ipam/filtersets.py:616 netbox/ipam/filtersets.py:856
#: netbox/ipam/filtersets.py:1131 netbox/vpn/filtersets.py:385
#: netbox/ipam/filtersets.py:618 netbox/ipam/filtersets.py:858
#: netbox/ipam/filtersets.py:1133 netbox/vpn/filtersets.py:385
msgid "Virtual machine (name)"
msgstr "Virtuelle Maschine (Name)"
#: netbox/ipam/filtersets.py:621 netbox/ipam/filtersets.py:861
#: netbox/ipam/filtersets.py:1125 netbox/virtualization/filtersets.py:282
#: netbox/ipam/filtersets.py:623 netbox/ipam/filtersets.py:863
#: netbox/ipam/filtersets.py:1127 netbox/virtualization/filtersets.py:282
#: netbox/virtualization/filtersets.py:321 netbox/vpn/filtersets.py:390
msgid "Virtual machine (ID)"
msgstr "Virtuelle Maschine (ID)"
#: netbox/ipam/filtersets.py:627 netbox/vpn/filtersets.py:97
#: netbox/ipam/filtersets.py:629 netbox/vpn/filtersets.py:97
#: netbox/vpn/filtersets.py:396
msgid "Interface (name)"
msgstr "Schnittstelle (Name)"
#: netbox/ipam/filtersets.py:638 netbox/vpn/filtersets.py:108
#: netbox/ipam/filtersets.py:640 netbox/vpn/filtersets.py:108
#: netbox/vpn/filtersets.py:407
msgid "VM interface (name)"
msgstr "VM-Schnittstelle (Name)"
#: netbox/ipam/filtersets.py:643 netbox/vpn/filtersets.py:113
#: netbox/ipam/filtersets.py:645 netbox/vpn/filtersets.py:113
msgid "VM interface (ID)"
msgstr "VM-Schnittstelle (ID)"
#: netbox/ipam/filtersets.py:648
#: netbox/ipam/filtersets.py:650
msgid "FHRP group (ID)"
msgstr "FHRP-Gruppe (ID)"
#: netbox/ipam/filtersets.py:652
#: netbox/ipam/filtersets.py:654
msgid "Is assigned to an interface"
msgstr "Ist einer Schnittstelle zugewiesen"
#: netbox/ipam/filtersets.py:656
#: netbox/ipam/filtersets.py:658
msgid "Is assigned"
msgstr "Ist zugewiesen"
#: netbox/ipam/filtersets.py:668
#: netbox/ipam/filtersets.py:670
msgid "Service (ID)"
msgstr "Dienst (ID)"
#: netbox/ipam/filtersets.py:673
#: netbox/ipam/filtersets.py:675
msgid "NAT inside IP address (ID)"
msgstr "NAT innerhalb der IP-Adresse (ID)"
msgstr "NAT inside IP-Adresse (ID)"
#: netbox/ipam/filtersets.py:1041 netbox/ipam/forms/bulk_import.py:322
#: netbox/ipam/filtersets.py:1043 netbox/ipam/forms/bulk_import.py:322
msgid "Assigned interface"
msgstr "Zugewiesene Schnittstelle"
#: netbox/ipam/filtersets.py:1046
#: netbox/ipam/filtersets.py:1048
msgid "Assigned VM interface"
msgstr "Zugewiesene VM-Schnittstelle"
#: netbox/ipam/filtersets.py:1136
#: netbox/ipam/filtersets.py:1138
msgid "IP address (ID)"
msgstr "IP-Adresse (ID)"
#: netbox/ipam/filtersets.py:1142 netbox/ipam/models/ip.py:788
#: netbox/ipam/filtersets.py:1144 netbox/ipam/models/ip.py:788
msgid "IP address"
msgstr "IP-Adresse"
#: netbox/ipam/filtersets.py:1167
#: netbox/ipam/filtersets.py:1169
msgid "Primary IPv4 (ID)"
msgstr "Primäre IPv4 (ID)"
#: netbox/ipam/filtersets.py:1172
#: netbox/ipam/filtersets.py:1174
msgid "Primary IPv6 (ID)"
msgstr "Primäre IPv6 (ID)"
@@ -9959,7 +9954,7 @@ msgstr "Ziel der Route"
#: netbox/templates/ipam/aggregate.html:11
#: netbox/templates/ipam/prefix.html:38
msgid "Aggregate"
msgstr "Aggregat"
msgstr "Aggregieren"
#: netbox/ipam/forms/model_forms.py:135 netbox/templates/ipam/asnrange.html:12
msgid "ASN Range"
@@ -9967,7 +9962,7 @@ msgstr "ASN-Bereich"
#: netbox/ipam/forms/model_forms.py:231
msgid "Site/VLAN Assignment"
msgstr "Standort-/VLAN-Zuweisung"
msgstr ""
#: netbox/ipam/forms/model_forms.py:259 netbox/templates/ipam/iprange.html:10
msgid "IP Range"
@@ -10095,9 +10090,7 @@ msgstr "ASN-Bereiche"
#: netbox/ipam/models/asns.py:72
#, python-brace-format
msgid "Starting ASN ({start}) must be lower than ending ASN ({end})."
msgstr ""
"ASN wird gestartet ({start}) muss niedriger sein als das Ende der ASN "
"({end})."
msgstr "Der ASN ({start}) muss niedriger sein als das letzte ASN ({end})."
#: netbox/ipam/models/asns.py:104
msgid "Regional Internet Registry responsible for this AS number space"
@@ -10171,7 +10164,7 @@ msgstr "Aggregat"
#: netbox/ipam/models/ip.py:116
msgid "aggregates"
msgstr "Aggregate"
msgstr "aggregiert"
#: netbox/ipam/models/ip.py:132
msgid "Cannot create aggregate with /0 mask."
@@ -10227,7 +10220,8 @@ msgstr "ist ein Pool"
#: netbox/ipam/models/ip.py:267
msgid "All IP addresses within this prefix are considered usable"
msgstr ""
"Alle IP-Adressen innerhalb dieses Prefixes werden als nutzbar betrachtet"
"Alle IP-Adressen (inklusive Netzwerk- und Broadcast-Adresse) innerhalb "
"dieses Prefixes werden als nutzbar betrachtet"
#: netbox/ipam/models/ip.py:270 netbox/ipam/models/ip.py:537
msgid "mark utilized"
@@ -10503,7 +10497,7 @@ msgstr "einzigartigen Raum erzwingen"
#: netbox/ipam/models/vrfs.py:43
msgid "Prevent duplicate prefixes/IP addresses within this VRF"
msgstr "Vermeiden Sie doppelte Präfixe/IP-Adressen in diesem VRF"
msgstr "Vermeiden Sie doppelte Präfixe/IP-Adressen in dieser VRF"
#: netbox/ipam/models/vrfs.py:63 netbox/netbox/navigation/menu.py:186
#: netbox/netbox/navigation/menu.py:188
@@ -10524,7 +10518,7 @@ msgstr "Routenziele"
#: netbox/ipam/tables/asn.py:52
msgid "ASDOT"
msgstr "ALS PUNKT"
msgstr "ASDOT"
#: netbox/ipam/tables/asn.py:57
msgid "Site Count"
@@ -11552,7 +11546,7 @@ msgstr ""
#: netbox/netbox/registry.py:14
#, python-brace-format
msgid "Invalid store: {key}"
msgstr "Ungültiger Shop: {key}"
msgstr "Ungültiger Store: {key}"
#: netbox/netbox/registry.py:17
msgid "Cannot add stores to registry after initialization"
@@ -12431,7 +12425,7 @@ msgstr "Warteschlange"
#: netbox/templates/core/rq_task.html:65
msgid "Timeout"
msgstr "Auszeit"
msgstr "Timeout"
#: netbox/templates/core/rq_task.html:69
msgid "Result TTL"
@@ -12501,7 +12495,7 @@ msgstr "Anzahl fehlgeschlagener Jobs"
#: netbox/templates/core/rq_worker.html:75
msgid "Total working time"
msgstr "Gesamtarbeitszeit"
msgstr "Gesamtlaufzeit"
#: netbox/templates/core/rq_worker.html:76
msgid "seconds"
@@ -12827,7 +12821,7 @@ msgstr "Fehler beim Rendern der Vorlage"
#: netbox/templates/dcim/device/render_config.html:70
msgid "No configuration template has been assigned for this device."
msgstr "Diesem Gerät wurde keine Konfigurationsvorlage zugewiesen."
msgstr ""
#: netbox/templates/dcim/device_edit.html:44
msgid "Parent Bay"
@@ -14098,7 +14092,7 @@ msgstr "Hilfecenter"
#: netbox/templates/inc/user_menu.html:41
msgid "Django Admin"
msgstr "Django-Admin"
msgstr ""
#: netbox/templates/inc/user_menu.html:61
msgid "Log Out"
@@ -14513,7 +14507,6 @@ msgstr "Virtuelles Laufwerk hinzufügen"
#: netbox/templates/virtualization/virtualmachine/render_config.html:70
msgid "No configuration template has been assigned for this virtual machine."
msgstr ""
"Für diese virtuelle Maschine wurde keine Konfigurationsvorlage zugewiesen."
#: netbox/templates/vpn/ikepolicy.html:10
#: netbox/templates/vpn/ipsecprofile.html:33 netbox/vpn/tables/crypto.py:166
@@ -14540,11 +14533,11 @@ msgstr "Secret anzeigen"
#: netbox/vpn/forms/model_forms.py:316 netbox/vpn/forms/model_forms.py:352
#: netbox/vpn/tables/crypto.py:68 netbox/vpn/tables/crypto.py:134
msgid "Proposals"
msgstr "Vorschläge"
msgstr "Proposals"
#: netbox/templates/vpn/ikeproposal.html:10
msgid "IKE Proposal"
msgstr "IKE-Vorschlag"
msgstr "IKE- Proposal"
#: netbox/templates/vpn/ikeproposal.html:21 netbox/vpn/forms/bulk_edit.py:97
#: netbox/vpn/forms/bulk_import.py:145 netbox/vpn/forms/filtersets.py:101
@@ -14575,7 +14568,7 @@ msgstr "DH-Gruppe"
#: netbox/templates/vpn/ipsecproposal.html:29
#: netbox/vpn/forms/bulk_edit.py:182 netbox/vpn/models/crypto.py:146
msgid "SA lifetime (seconds)"
msgstr "SA-Lebensdauer (Sekunden)"
msgstr "SA-Gültigkeitsdauer (Sekunden)"
#: netbox/templates/vpn/ipsecpolicy.html:10
#: netbox/templates/vpn/ipsecprofile.html:66 netbox/vpn/tables/crypto.py:170
@@ -14660,7 +14653,7 @@ msgstr "Peer-Abschlusspunkt"
#: netbox/templates/wireless/inc/authentication_attrs.html:12
msgid "Cipher"
msgstr "Chiffre"
msgstr "Verschlüsselungsalgorithmus"
#: netbox/templates/wireless/inc/authentication_attrs.html:16
msgid "PSK"
@@ -15638,8 +15631,6 @@ msgid ""
"{device} belongs to a different site ({device_site}) than the cluster "
"({cluster_site})"
msgstr ""
"{device} gehört zu einerm anderen Standort ({device_site}) als das Cluster "
"({cluster_site})"
#: netbox/virtualization/forms/model_forms.py:192
msgid "Optionally pin this VM to a specific host device within the cluster"
@@ -15977,7 +15968,7 @@ msgstr "SA-Lebendauer"
#: netbox/wireless/forms/filtersets.py:64
#: netbox/wireless/forms/filtersets.py:98
msgid "Pre-shared key"
msgstr "Vorab geteilter Schlüssel (Pre-shared key)"
msgstr "Vorab geteilter Schlüssel (PSK)"
#: netbox/vpn/forms/bulk_edit.py:237 netbox/vpn/forms/bulk_import.py:239
#: netbox/vpn/forms/filtersets.py:199 netbox/vpn/forms/model_forms.py:370
@@ -15993,7 +15984,7 @@ msgstr "IPSec-Richtlinie"
#: netbox/vpn/forms/bulk_import.py:50
msgid "Tunnel encapsulation"
msgstr "Tunnelkapselung"
msgstr "Tunnel Encapsulation"
#: netbox/vpn/forms/bulk_import.py:83
msgid "Operational role"
@@ -16140,7 +16131,7 @@ msgstr "Vorschläge"
#: netbox/vpn/models/crypto.py:91 netbox/wireless/models.py:39
msgid "pre-shared key"
msgstr "vorab geteilter Schlüssel"
msgstr "vorab geteilter Schlüssel (PSK)"
#: netbox/vpn/models/crypto.py:105
msgid "IKE policies"
@@ -16273,7 +16264,7 @@ msgstr "SA-Lebensdauer"
#: netbox/vpn/tables/crypto.py:71
msgid "Pre-shared Key"
msgstr "Vorab geteilter Schlüssel"
msgstr "Vorab geteilter Schlüssel (PSK)"
#: netbox/vpn/tables/crypto.py:103
msgid "SA Lifetime (Seconds)"
@@ -16390,7 +16381,6 @@ msgstr "Funkverbindungen"
#: netbox/wireless/models.py:236
msgid "Must specify a unit when setting a wireless distance"
msgstr ""
"Beim Einstellen einer Funkentfernung muss eine Einheit angegeben werden"
#: netbox/wireless/models.py:242 netbox/wireless/models.py:248
#, python-brace-format

Some files were not shown because too many files have changed in this diff Show More