mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-13 16:47:34 -06:00
Merge branch 'develop' into feature
This commit is contained in:
commit
e370cadcef
@ -14,7 +14,7 @@ body:
|
||||
attributes:
|
||||
label: NetBox version
|
||||
description: What version of NetBox are you currently running?
|
||||
placeholder: v4.1.3
|
||||
placeholder: v4.1.4
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
|
2
.github/ISSUE_TEMPLATE/02-bug_report.yaml
vendored
2
.github/ISSUE_TEMPLATE/02-bug_report.yaml
vendored
@ -40,7 +40,7 @@ body:
|
||||
attributes:
|
||||
label: NetBox Version
|
||||
description: What version of NetBox are you currently running?
|
||||
placeholder: v4.1.3
|
||||
placeholder: v4.1.4
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
|
44
.pre-commit-config.yaml
Normal file
44
.pre-commit-config.yaml
Normal file
@ -0,0 +1,44 @@
|
||||
repos:
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
rev: v0.6.9
|
||||
hooks:
|
||||
- id: ruff
|
||||
name: "Ruff linter"
|
||||
args: [ netbox/ ]
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: django-check
|
||||
name: "Django system check"
|
||||
description: "Run Django's internal check for common problems"
|
||||
entry: python netbox/manage.py check
|
||||
language: system
|
||||
pass_filenames: false
|
||||
types: [python]
|
||||
- id: django-makemigrations
|
||||
name: "Django migrations check"
|
||||
description: "Check for any missing Django migrations"
|
||||
entry: python netbox/manage.py makemigrations --check
|
||||
language: system
|
||||
pass_filenames: false
|
||||
types: [python]
|
||||
- id: mkdocs-build
|
||||
name: "Build documentation"
|
||||
description: "Build the documentation with mkdocs"
|
||||
files: 'docs/'
|
||||
entry: mkdocs build
|
||||
language: system
|
||||
pass_filenames: false
|
||||
- id: yarn-validate
|
||||
name: "Yarn validate"
|
||||
description: "Check UI ESLint, TypeScript, and Prettier compliance"
|
||||
files: 'netbox/project-static/'
|
||||
entry: yarn --cwd netbox/project-static validate
|
||||
language: system
|
||||
pass_filenames: false
|
||||
- id: verify-bundles
|
||||
name: "Verify static asset bundles"
|
||||
description: "Ensure that any modified static assets have been compiled"
|
||||
files: 'netbox/project-static/'
|
||||
entry: scripts/verify-bundles.sh
|
||||
language: system
|
||||
pass_filenames: false
|
@ -12,6 +12,9 @@
|
||||
"left-to-right",
|
||||
"right-to-left",
|
||||
"side-to-rear",
|
||||
"rear-to-side",
|
||||
"bottom-to-top",
|
||||
"top-to-bottom",
|
||||
"passive",
|
||||
"mixed"
|
||||
]
|
||||
|
@ -62,22 +62,7 @@ $issue-$description
|
||||
|
||||
The description should be just two or three words to imply the focus of the work being performed. For example, bug #1234 to fix a TypeError exception when creating a device might be named `1234-device-typerror`. This ensures that branches are always follow some logical ordering (e.g. when running `git branch -a`) and helps other developers quickly identify the purpose of each.
|
||||
|
||||
### 3. Enable Pre-Commit Hooks
|
||||
|
||||
NetBox ships with a [git pre-commit hook](https://githooks.com/) script that automatically checks for style compliance and missing database migrations prior to committing changes. This helps avoid erroneous commits that result in CI test failures. You are encouraged to enable it by creating a link to `scripts/git-hooks/pre-commit`:
|
||||
|
||||
```no-highlight
|
||||
cd .git/hooks/
|
||||
ln -s ../../scripts/git-hooks/pre-commit
|
||||
```
|
||||
For the pre-commit hooks to work, you will also need to install the [ruff](https://docs.astral.sh/ruff/) linter:
|
||||
|
||||
```no-highlight
|
||||
python -m pip install ruff
|
||||
```
|
||||
...and set up the yarn packages as shown in the [Web UI Development Guide](web-ui.md)
|
||||
|
||||
### 4. Create a Python Virtual Environment
|
||||
### 3. Create a Python Virtual Environment
|
||||
|
||||
A [virtual environment](https://docs.python.org/3/tutorial/venv.html) (or "venv" for short) is like a container for a set of Python packages. These allow you to build environments suited to specific projects without interfering with system packages or other projects. When installed per the documentation, NetBox uses a virtual environment in production.
|
||||
|
||||
@ -101,7 +86,7 @@ source ~/.venv/netbox/bin/activate
|
||||
|
||||
Notice that the console prompt changes to indicate the active environment. This updates the necessary system environment variables to ensure that any Python scripts are run within the virtual environment.
|
||||
|
||||
### 5. Install Required Packages
|
||||
### 4. Install Required Packages
|
||||
|
||||
With the virtual environment activated, install the project's required Python packages using the `pip` module. Required packages are defined in `requirements.txt`. Each line in this file specifies the name and specific version of a required package.
|
||||
|
||||
@ -109,6 +94,26 @@ With the virtual environment activated, install the project's required Python pa
|
||||
python -m pip install -r requirements.txt
|
||||
```
|
||||
|
||||
### 5. Install Pre-Commit
|
||||
|
||||
NetBox uses [`pre-commit`](https://pre-commit.com/) to automatically validate code when commiting new changes. This includes the following operations:
|
||||
|
||||
* Run the `ruff` Python linter
|
||||
* Run Django's internal system check
|
||||
* Check for missing database migrations
|
||||
* Validate any changes to the documentation with `mkdocs`
|
||||
* Validate Typescript & Sass styling with `yarn`
|
||||
* Ensure that any modified static front end assets have been recompiled
|
||||
|
||||
Enable `pre-commit` with the following commands _prior_ to commiting any changes:
|
||||
|
||||
```no-highlight
|
||||
python -m pip install ruff pre-commit
|
||||
pre-commit install
|
||||
```
|
||||
|
||||
You may also need to set up the yarn packages as shown in the [Web UI Development Guide](web-ui.md).
|
||||
|
||||
### 6. Configure NetBox
|
||||
|
||||
Within the `netbox/netbox/` directory, copy `configuration_example.py` to `configuration.py` and update the following parameters:
|
||||
|
@ -1,11 +1,12 @@
|
||||
# NetBox v4.1
|
||||
|
||||
## v4.1.4 (FUTURE)
|
||||
## v4.1.4 (2024-10-15)
|
||||
|
||||
### Enhancements
|
||||
|
||||
* [#11671](https://github.com/netbox-community/netbox/issues/11671) - Display device's rack position in cable traces
|
||||
* [#15829](https://github.com/netbox-community/netbox/issues/15829) - Rename Microsoft Azure AD SSO backend to Microsoft Entra ID
|
||||
* [#16009](https://github.com/netbox-community/netbox/issues/16009) - Float form & bulk operation buttons within UI
|
||||
* [#17079](https://github.com/netbox-community/netbox/issues/17079) - Introduce additional choices for device airflow direction
|
||||
* [#17216](https://github.com/netbox-community/netbox/issues/17216) - Add EVPN-VPWS L2VPN type
|
||||
* [#17655](https://github.com/netbox-community/netbox/issues/17655) - Limit the display of tagged VLANs within interface tables
|
||||
@ -14,12 +15,16 @@
|
||||
### Bug Fixes
|
||||
|
||||
* [#16024](https://github.com/netbox-community/netbox/issues/16024) - Fix AND/OR filtering in GraphQL API for selection fields
|
||||
* [#17400](https://github.com/netbox-community/netbox/issues/17400) - Fix cable tracing across split paths
|
||||
* [#17562](https://github.com/netbox-community/netbox/issues/17562) - Fix GraphQL API query support for custom field choices
|
||||
* [#17566](https://github.com/netbox-community/netbox/issues/17566) - Fix AttributeError exception resulting from background jobs with no associated object type
|
||||
* [#17614](https://github.com/netbox-community/netbox/issues/17614) - Disallow removal of a master device from its virtual chassis
|
||||
* [#17636](https://github.com/netbox-community/netbox/issues/17636) - Fix filtering of related objects when adding a power port, rear port, or inventory item template to a device type
|
||||
* [#17644](https://github.com/netbox-community/netbox/issues/17644) - Correct sizing of logo & SSO icons on login page
|
||||
* [#17648](https://github.com/netbox-community/netbox/issues/17648) - Fix AttributeError exception when attempting to delete a background job under certain conditions
|
||||
* [#17663](https://github.com/netbox-community/netbox/issues/17663) - Fix extended lookups for choice field filters
|
||||
* [#17671](https://github.com/netbox-community/netbox/issues/17671) - Fix the display of rack types in global search results
|
||||
* [#17713](https://github.com/netbox-community/netbox/issues/17713) - Fix UnboundLocalError exception when attempting to sync data source in parallel
|
||||
|
||||
---
|
||||
|
||||
|
@ -662,6 +662,14 @@ class CablePath(models.Model):
|
||||
rear_port_id=remote_terminations[0].pk,
|
||||
rear_port_position__in=position_stack.pop()
|
||||
)
|
||||
# If all rear ports have a single position, we can just get the front ports
|
||||
elif all([rp.positions == 1 for rp in remote_terminations]):
|
||||
front_ports = FrontPort.objects.filter(rear_port_id__in=[rp.pk for rp in remote_terminations])
|
||||
|
||||
if len(front_ports) != len(remote_terminations):
|
||||
# Some rear ports does not have a front port
|
||||
is_split = True
|
||||
break
|
||||
else:
|
||||
# No position indicated: path has split, so we stop at the RearPorts
|
||||
is_split = True
|
||||
|
@ -966,6 +966,13 @@ class Device(
|
||||
'vc_position': _("A device assigned to a virtual chassis must have its position defined.")
|
||||
})
|
||||
|
||||
if hasattr(self, 'vc_master_for') and self.vc_master_for and self.vc_master_for != self.virtual_chassis:
|
||||
raise ValidationError({
|
||||
'virtual_chassis': _('Device cannot be removed from virtual chassis {virtual_chassis} because it is currently designated as its master.').format(
|
||||
virtual_chassis=self.vc_master_for
|
||||
)
|
||||
})
|
||||
|
||||
def _instantiate_components(self, queryset, bulk_create=True):
|
||||
"""
|
||||
Instantiate components for the device from the specified component templates.
|
||||
|
@ -2060,6 +2060,49 @@ class CablePathTestCase(TestCase):
|
||||
# Test SVG generation
|
||||
CableTraceSVG(interface1).render()
|
||||
|
||||
def test_222_single_path_via_multiple_singleposition_rear_ports(self):
|
||||
"""
|
||||
[IF1] --C1-- [FP1] [RP1] --C2-- [IF2]
|
||||
[FP2] [RP2]
|
||||
"""
|
||||
interface1 = Interface.objects.create(device=self.device, name='Interface 1')
|
||||
interface2 = Interface.objects.create(device=self.device, name='Interface 2')
|
||||
rearport1 = RearPort.objects.create(device=self.device, name='Rear Port 1', positions=1)
|
||||
rearport2 = RearPort.objects.create(device=self.device, name='Rear Port 2', positions=1)
|
||||
frontport1 = FrontPort.objects.create(
|
||||
device=self.device, name='Front Port 1', rear_port=rearport1, rear_port_position=1
|
||||
)
|
||||
frontport2 = FrontPort.objects.create(
|
||||
device=self.device, name='Front Port 2', rear_port=rearport2, rear_port_position=1
|
||||
)
|
||||
|
||||
cable1 = Cable(
|
||||
a_terminations=[interface1],
|
||||
b_terminations=[frontport1, frontport2]
|
||||
)
|
||||
cable1.save()
|
||||
self.assertEqual(CablePath.objects.count(), 1)
|
||||
|
||||
cable2 = Cable(
|
||||
a_terminations=[rearport1, rearport2],
|
||||
b_terminations=[interface2]
|
||||
)
|
||||
cable2.save()
|
||||
self.assertEqual(CablePath.objects.count(), 2)
|
||||
|
||||
self.assertPathExists(
|
||||
(interface1, cable1, (frontport1, frontport2), (rearport1, rearport2), cable2, interface2),
|
||||
is_complete=True
|
||||
)
|
||||
self.assertPathExists(
|
||||
(interface2, cable2, (rearport1, rearport2), (frontport1, frontport2), cable1, interface1),
|
||||
is_complete=True
|
||||
)
|
||||
|
||||
# Test SVG generation both directions
|
||||
CableTraceSVG(interface1).render()
|
||||
CableTraceSVG(interface2).render()
|
||||
|
||||
def test_301_create_path_via_existing_cable(self):
|
||||
"""
|
||||
[IF1] --C1-- [FP1] [RP1] --C2-- [RP2] [FP2] --C3-- [IF2]
|
||||
|
@ -1,10 +1,6 @@
|
||||
import json
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.views import redirect_to_login
|
||||
from django.http import HttpResponseNotFound, HttpResponseForbidden
|
||||
from django.http import HttpResponse
|
||||
from django.template import loader
|
||||
from django.urls import reverse
|
||||
from django.views.decorators.csrf import csrf_exempt
|
||||
from rest_framework.exceptions import AuthenticationFailed
|
||||
@ -46,9 +42,3 @@ class NetBoxGraphQLView(GraphQLView):
|
||||
return HttpResponseForbidden("No credentials provided.")
|
||||
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
def render_graphql_ide(self, request):
|
||||
template = loader.get_template("graphiql.html")
|
||||
context = {"SUBSCRIPTION_ENABLED": json.dumps(self.subscriptions_enabled)}
|
||||
|
||||
return HttpResponse(template.render(context, request))
|
||||
|
BIN
netbox/project-static/dist/netbox.css
vendored
BIN
netbox/project-static/dist/netbox.css
vendored
Binary file not shown.
BIN
netbox/project-static/dist/netbox.js
vendored
BIN
netbox/project-static/dist/netbox.js
vendored
Binary file not shown.
BIN
netbox/project-static/dist/netbox.js.map
vendored
BIN
netbox/project-static/dist/netbox.js.map
vendored
Binary file not shown.
@ -29,8 +29,8 @@
|
||||
"flatpickr": "4.6.13",
|
||||
"gridstack": "10.3.1",
|
||||
"htmx.org": "1.9.12",
|
||||
"query-string": "9.1.0",
|
||||
"sass": "1.79.3",
|
||||
"query-string": "9.1.1",
|
||||
"sass": "1.79.5",
|
||||
"tom-select": "2.3.1",
|
||||
"typeface-inter": "3.18.1",
|
||||
"typeface-roboto-mono": "1.1.13"
|
||||
|
42
netbox/project-static/src/buttons/floatBulk.ts
Normal file
42
netbox/project-static/src/buttons/floatBulk.ts
Normal file
@ -0,0 +1,42 @@
|
||||
import { getElements } from '../util';
|
||||
|
||||
/**
|
||||
* Conditionally add and remove a class that will float the button group
|
||||
* based on whether or not items in the list are checked
|
||||
*/
|
||||
function toggleFloat(): void {
|
||||
const checkedCheckboxes = document.querySelector<HTMLInputElement>(
|
||||
'input[type="checkbox"][name="pk"]:checked',
|
||||
);
|
||||
const buttonGroup = document.querySelector<HTMLDivElement>(
|
||||
'div.form.form-horizontal div.btn-list',
|
||||
);
|
||||
if (!buttonGroup) {
|
||||
return;
|
||||
}
|
||||
const isFloating = buttonGroup.classList.contains('btn-float-group-left');
|
||||
if (checkedCheckboxes !== null && !isFloating) {
|
||||
buttonGroup.classList.add('btn-float-group-left');
|
||||
} else if (checkedCheckboxes === null && isFloating) {
|
||||
buttonGroup.classList.remove('btn-float-group-left');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize floating bulk buttons.
|
||||
*/
|
||||
export function initFloatBulk(): void {
|
||||
for (const element of getElements<HTMLInputElement>('input[type="checkbox"][name="pk"]')) {
|
||||
element.addEventListener('change', () => {
|
||||
toggleFloat();
|
||||
});
|
||||
}
|
||||
// Handle the select-all checkbox
|
||||
for (const element of getElements<HTMLInputElement>(
|
||||
'table tr th > input[type="checkbox"].toggle',
|
||||
)) {
|
||||
element.addEventListener('change', () => {
|
||||
toggleFloat();
|
||||
});
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@ import { initDepthToggle } from './depthToggle';
|
||||
import { initMoveButtons } from './moveOptions';
|
||||
import { initReslug } from './reslug';
|
||||
import { initSelectAll } from './selectAll';
|
||||
import { initFloatBulk } from './floatBulk';
|
||||
import { initSelectMultiple } from './selectMultiple';
|
||||
import { initMarkdownPreviews } from './markdownPreview';
|
||||
import { initSecretToggle } from './secretToggle';
|
||||
@ -14,6 +15,7 @@ export function initButtons(): void {
|
||||
initReslug,
|
||||
initSelectAll,
|
||||
initSelectMultiple,
|
||||
initFloatBulk,
|
||||
initMoveButtons,
|
||||
initMarkdownPreviews,
|
||||
initSecretToggle,
|
||||
|
@ -33,3 +33,33 @@ span.color-label {
|
||||
.netbox-edition {
|
||||
letter-spacing: .15rem;
|
||||
}
|
||||
|
||||
// A floating div for form buttons
|
||||
.btn-float-group {
|
||||
position: sticky;
|
||||
bottom: 10px;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.btn-float-group-left {
|
||||
@extend .btn-float-group;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.btn-float-group-right {
|
||||
@extend .btn-float-group;
|
||||
float: right;
|
||||
}
|
||||
|
||||
// Override a transparent background
|
||||
.btn-float {
|
||||
--tblr-btn-bg: var(--#{$prefix}bg-surface-tertiary) !important;
|
||||
}
|
||||
|
||||
.logo {
|
||||
height: 80px;
|
||||
}
|
||||
|
||||
.sso-icon {
|
||||
height: 24px;
|
||||
}
|
||||
|
@ -365,6 +365,89 @@
|
||||
resolved "https://registry.yarnpkg.com/@orchidjs/unicode-variants/-/unicode-variants-1.0.4.tgz#6d2f812e3b19545bba2d81caffff1204de9a6a58"
|
||||
integrity sha512-NvVBRnZNE+dugiXERFsET1JlKZfM5lJDEpSMilKW4bToYJ7pxf0Zne78xyXB2ny2c2aHfJ6WLnz1AaTNHAmQeQ==
|
||||
|
||||
"@parcel/watcher-android-arm64@2.4.1":
|
||||
version "2.4.1"
|
||||
resolved "https://registry.yarnpkg.com/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.4.1.tgz#c2c19a3c442313ff007d2d7a9c2c1dd3e1c9ca84"
|
||||
integrity sha512-LOi/WTbbh3aTn2RYddrO8pnapixAziFl6SMxHM69r3tvdSm94JtCenaKgk1GRg5FJ5wpMCpHeW+7yqPlvZv7kg==
|
||||
|
||||
"@parcel/watcher-darwin-arm64@2.4.1":
|
||||
version "2.4.1"
|
||||
resolved "https://registry.yarnpkg.com/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.4.1.tgz#c817c7a3b4f3a79c1535bfe54a1c2818d9ffdc34"
|
||||
integrity sha512-ln41eihm5YXIY043vBrrHfn94SIBlqOWmoROhsMVTSXGh0QahKGy77tfEywQ7v3NywyxBBkGIfrWRHm0hsKtzA==
|
||||
|
||||
"@parcel/watcher-darwin-x64@2.4.1":
|
||||
version "2.4.1"
|
||||
resolved "https://registry.yarnpkg.com/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.4.1.tgz#1a3f69d9323eae4f1c61a5f480a59c478d2cb020"
|
||||
integrity sha512-yrw81BRLjjtHyDu7J61oPuSoeYWR3lDElcPGJyOvIXmor6DEo7/G2u1o7I38cwlcoBHQFULqF6nesIX3tsEXMg==
|
||||
|
||||
"@parcel/watcher-freebsd-x64@2.4.1":
|
||||
version "2.4.1"
|
||||
resolved "https://registry.yarnpkg.com/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.4.1.tgz#0d67fef1609f90ba6a8a662bc76a55fc93706fc8"
|
||||
integrity sha512-TJa3Pex/gX3CWIx/Co8k+ykNdDCLx+TuZj3f3h7eOjgpdKM+Mnix37RYsYU4LHhiYJz3DK5nFCCra81p6g050w==
|
||||
|
||||
"@parcel/watcher-linux-arm-glibc@2.4.1":
|
||||
version "2.4.1"
|
||||
resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.4.1.tgz#ce5b340da5829b8e546bd00f752ae5292e1c702d"
|
||||
integrity sha512-4rVYDlsMEYfa537BRXxJ5UF4ddNwnr2/1O4MHM5PjI9cvV2qymvhwZSFgXqbS8YoTk5i/JR0L0JDs69BUn45YA==
|
||||
|
||||
"@parcel/watcher-linux-arm64-glibc@2.4.1":
|
||||
version "2.4.1"
|
||||
resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.4.1.tgz#6d7c00dde6d40608f9554e73998db11b2b1ff7c7"
|
||||
integrity sha512-BJ7mH985OADVLpbrzCLgrJ3TOpiZggE9FMblfO65PlOCdG++xJpKUJ0Aol74ZUIYfb8WsRlUdgrZxKkz3zXWYA==
|
||||
|
||||
"@parcel/watcher-linux-arm64-musl@2.4.1":
|
||||
version "2.4.1"
|
||||
resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.4.1.tgz#bd39bc71015f08a4a31a47cd89c236b9d6a7f635"
|
||||
integrity sha512-p4Xb7JGq3MLgAfYhslU2SjoV9G0kI0Xry0kuxeG/41UfpjHGOhv7UoUDAz/jb1u2elbhazy4rRBL8PegPJFBhA==
|
||||
|
||||
"@parcel/watcher-linux-x64-glibc@2.4.1":
|
||||
version "2.4.1"
|
||||
resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.4.1.tgz#0ce29966b082fb6cdd3de44f2f74057eef2c9e39"
|
||||
integrity sha512-s9O3fByZ/2pyYDPoLM6zt92yu6P4E39a03zvO0qCHOTjxmt3GHRMLuRZEWhWLASTMSrrnVNWdVI/+pUElJBBBg==
|
||||
|
||||
"@parcel/watcher-linux-x64-musl@2.4.1":
|
||||
version "2.4.1"
|
||||
resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.4.1.tgz#d2ebbf60e407170bb647cd6e447f4f2bab19ad16"
|
||||
integrity sha512-L2nZTYR1myLNST0O632g0Dx9LyMNHrn6TOt76sYxWLdff3cB22/GZX2UPtJnaqQPdCRoszoY5rcOj4oMTtp5fQ==
|
||||
|
||||
"@parcel/watcher-win32-arm64@2.4.1":
|
||||
version "2.4.1"
|
||||
resolved "https://registry.yarnpkg.com/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.4.1.tgz#eb4deef37e80f0b5e2f215dd6d7a6d40a85f8adc"
|
||||
integrity sha512-Uq2BPp5GWhrq/lcuItCHoqxjULU1QYEcyjSO5jqqOK8RNFDBQnenMMx4gAl3v8GiWa59E9+uDM7yZ6LxwUIfRg==
|
||||
|
||||
"@parcel/watcher-win32-ia32@2.4.1":
|
||||
version "2.4.1"
|
||||
resolved "https://registry.yarnpkg.com/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.4.1.tgz#94fbd4b497be39fd5c8c71ba05436927842c9df7"
|
||||
integrity sha512-maNRit5QQV2kgHFSYwftmPBxiuK5u4DXjbXx7q6eKjq5dsLXZ4FJiVvlcw35QXzk0KrUecJmuVFbj4uV9oYrcw==
|
||||
|
||||
"@parcel/watcher-win32-x64@2.4.1":
|
||||
version "2.4.1"
|
||||
resolved "https://registry.yarnpkg.com/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.4.1.tgz#4bf920912f67cae5f2d264f58df81abfea68dadf"
|
||||
integrity sha512-+DvS92F9ezicfswqrvIRM2njcYJbd5mb9CUgtrHCHmvn7pPPa+nMDRu1o1bYYz/l5IB2NVGNJWiH7h1E58IF2A==
|
||||
|
||||
"@parcel/watcher@^2.4.1":
|
||||
version "2.4.1"
|
||||
resolved "https://registry.yarnpkg.com/@parcel/watcher/-/watcher-2.4.1.tgz#a50275151a1bb110879c6123589dba90c19f1bf8"
|
||||
integrity sha512-HNjmfLQEVRZmHRET336f20H/8kOozUGwk7yajvsonjNxbj2wBTK1WsQuHkD5yYh9RxFGL2EyDHryOihOwUoKDA==
|
||||
dependencies:
|
||||
detect-libc "^1.0.3"
|
||||
is-glob "^4.0.3"
|
||||
micromatch "^4.0.5"
|
||||
node-addon-api "^7.0.0"
|
||||
optionalDependencies:
|
||||
"@parcel/watcher-android-arm64" "2.4.1"
|
||||
"@parcel/watcher-darwin-arm64" "2.4.1"
|
||||
"@parcel/watcher-darwin-x64" "2.4.1"
|
||||
"@parcel/watcher-freebsd-x64" "2.4.1"
|
||||
"@parcel/watcher-linux-arm-glibc" "2.4.1"
|
||||
"@parcel/watcher-linux-arm64-glibc" "2.4.1"
|
||||
"@parcel/watcher-linux-arm64-musl" "2.4.1"
|
||||
"@parcel/watcher-linux-x64-glibc" "2.4.1"
|
||||
"@parcel/watcher-linux-x64-musl" "2.4.1"
|
||||
"@parcel/watcher-win32-arm64" "2.4.1"
|
||||
"@parcel/watcher-win32-ia32" "2.4.1"
|
||||
"@parcel/watcher-win32-x64" "2.4.1"
|
||||
|
||||
"@pkgr/core@^0.1.0":
|
||||
version "0.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.1.1.tgz#1ec17e2edbec25c8306d424ecfbf13c7de1aaa31"
|
||||
@ -1196,6 +1279,11 @@ delegate@^3.1.2:
|
||||
resolved "https://registry.yarnpkg.com/delegate/-/delegate-3.2.0.tgz#b66b71c3158522e8ab5744f720d8ca0c2af59166"
|
||||
integrity sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==
|
||||
|
||||
detect-libc@^1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b"
|
||||
integrity sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==
|
||||
|
||||
detect-node-es@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/detect-node-es/-/detect-node-es-1.1.0.tgz#163acdf643330caa0b4cd7c21e7ee7755d6fa493"
|
||||
@ -2205,7 +2293,7 @@ meros@^1.1.4:
|
||||
resolved "https://registry.yarnpkg.com/meros/-/meros-1.3.0.tgz#c617d2092739d55286bf618129280f362e6242f2"
|
||||
integrity sha512-2BNGOimxEz5hmjUG2FwoxCt5HN7BXdaWyFqEwxPTrJzVdABtrL4TiHTcsWSFAxPQ/tOnEaQEJh3qWq71QRMY+w==
|
||||
|
||||
micromatch@^4.0.4:
|
||||
micromatch@^4.0.4, micromatch@^4.0.5:
|
||||
version "4.0.8"
|
||||
resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202"
|
||||
integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==
|
||||
@ -2247,6 +2335,11 @@ natural-compare@^1.4.0:
|
||||
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
|
||||
integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==
|
||||
|
||||
node-addon-api@^7.0.0:
|
||||
version "7.1.1"
|
||||
resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-7.1.1.tgz#1aba6693b0f255258a049d621329329322aad558"
|
||||
integrity sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==
|
||||
|
||||
normalize-path@^3.0.0, normalize-path@~3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
|
||||
@ -2417,10 +2510,10 @@ punycode@^2.1.0:
|
||||
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5"
|
||||
integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==
|
||||
|
||||
query-string@9.1.0:
|
||||
version "9.1.0"
|
||||
resolved "https://registry.yarnpkg.com/query-string/-/query-string-9.1.0.tgz#5f12a4653a4ba56021e113b5cf58e56581823e7a"
|
||||
integrity sha512-t6dqMECpCkqfyv2FfwVS1xcB6lgXW/0XZSaKdsCNGYkqMO76AFiJEg4vINzoDKcZa6MS7JX+OHIjwh06K5vczw==
|
||||
query-string@9.1.1:
|
||||
version "9.1.1"
|
||||
resolved "https://registry.yarnpkg.com/query-string/-/query-string-9.1.1.tgz#dbfebb4196aeb2919915f2b2b81b91b965cf03a0"
|
||||
integrity sha512-MWkCOVIcJP9QSKU52Ngow6bsAWAPlPK2MludXvcrS2bGZSl+T1qX9MZvRIkqUIkGLJquMJHWfsT6eRqUpp4aWg==
|
||||
dependencies:
|
||||
decode-uri-component "^0.4.1"
|
||||
filter-obj "^5.1.0"
|
||||
@ -2563,11 +2656,12 @@ safe-regex-test@^1.0.3:
|
||||
es-errors "^1.3.0"
|
||||
is-regex "^1.1.4"
|
||||
|
||||
sass@1.79.3:
|
||||
version "1.79.3"
|
||||
resolved "https://registry.yarnpkg.com/sass/-/sass-1.79.3.tgz#7811b000eb68195fe51dea89177e73e7ef7f546f"
|
||||
integrity sha512-m7dZxh0W9EZ3cw50Me5GOuYm/tVAJAn91SUnohLRo9cXBixGUOdvmryN+dXpwR831bhoY3Zv7rEFt85PUwTmzA==
|
||||
sass@1.79.5:
|
||||
version "1.79.5"
|
||||
resolved "https://registry.yarnpkg.com/sass/-/sass-1.79.5.tgz#646c627601cd5f84c64f7b1485b9292a313efae4"
|
||||
integrity sha512-W1h5kp6bdhqFh2tk3DsI771MoEJjvrSY/2ihJRJS4pjIyfJCw0nTsxqhnrUzaLMOJjFchj8rOvraI/YUVjtx5g==
|
||||
dependencies:
|
||||
"@parcel/watcher" "^2.4.1"
|
||||
chokidar "^4.0.0"
|
||||
immutable "^4.0.0"
|
||||
source-map-js ">=0.6.2 <2.0.0"
|
||||
|
@ -1,3 +1,3 @@
|
||||
version: "4.1.3"
|
||||
version: "4.1.4"
|
||||
edition: "Community"
|
||||
published: "2024-10-02"
|
||||
published: "2024-10-15"
|
||||
|
@ -102,8 +102,8 @@ Context:
|
||||
|
||||
{% endif %}
|
||||
|
||||
<div class="text-end">
|
||||
<a href="{{ return_url }}" class="btn btn-outline-secondary">{% trans "Cancel" %}</a>
|
||||
<div class="btn-float-group-right">
|
||||
<a href="{{ return_url }}" class="btn btn-outline-secondary btn-float">{% trans "Cancel" %}</a>
|
||||
<button type="submit" name="_apply" class="btn btn-primary">{% trans "Apply" %}</button>
|
||||
</div>
|
||||
|
||||
|
@ -67,9 +67,9 @@ Context:
|
||||
{% endblock form %}
|
||||
</div>
|
||||
|
||||
<div class="text-end my-3">
|
||||
<div class="btn-float-group-right">
|
||||
{% block buttons %}
|
||||
<a href="{{ return_url }}" class="btn btn-outline-secondary">{% trans "Cancel" %}</a>
|
||||
<a href="{{ return_url }}" class="btn btn-outline-secondary btn-float">{% trans "Cancel" %}</a>
|
||||
{% if object.pk %}
|
||||
<button type="submit" name="_update" class="btn btn-primary">
|
||||
{% trans "Save" %}
|
||||
@ -79,7 +79,7 @@ Context:
|
||||
<button type="submit" name="_create" class="btn btn-primary">
|
||||
{% trans "Create" %}
|
||||
</button>
|
||||
<button type="submit" name="_addanother" class="btn btn-outline-primary">
|
||||
<button type="submit" name="_addanother" class="btn btn-outline-primary btn-float">
|
||||
{% trans "Create & Add Another" %}
|
||||
</button>
|
||||
</div>
|
||||
|
@ -121,7 +121,7 @@ Context:
|
||||
{# /Objects table #}
|
||||
|
||||
{# Form buttons #}
|
||||
<div class="btn-list d-print-none mt-2">
|
||||
<div class="btn-list d-print-none">
|
||||
{% block bulk_buttons %}
|
||||
<div class="bulk-action-buttons">
|
||||
{% if 'bulk_edit' in actions %}
|
||||
|
@ -37,13 +37,13 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="card-footer text-end d-print-none border-0">
|
||||
<button type="button" class="btn btn-outline-danger m-1" data-reset-select>
|
||||
<i class="mdi mdi-backspace"></i> {% trans "Reset" %}
|
||||
</button>
|
||||
<button type="submit" class="btn btn-primary m-1">
|
||||
<i class="mdi mdi-magnify"></i> {% trans "Search" %}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="btn-float-group-right me-1">
|
||||
<button type="button" class="btn btn-outline-danger btn-float" data-reset-select>
|
||||
<i class="mdi mdi-backspace"></i> {% trans "Reset" %}
|
||||
</button>
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<i class="mdi mdi-magnify"></i> {% trans "Search" %}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -11,8 +11,8 @@
|
||||
|
||||
{# NetBox logo #}
|
||||
<div class="text-center mb-4">
|
||||
<img src="{% static 'logo_netbox_dark_teal.svg' %}" alt="{% trans "NetBox Logo" %}" height="80" class="hide-theme-dark">
|
||||
<img src="{% static 'logo_netbox_bright_teal.svg' %}" alt="{% trans "NetBox Logo" %}" height="80" class="hide-theme-light">
|
||||
<img src="{% static 'logo_netbox_dark_teal.svg' %}" alt="{% trans "NetBox Logo" %}" height="80" class="hide-theme-dark logo">
|
||||
<img src="{% static 'logo_netbox_bright_teal.svg' %}" alt="{% trans "NetBox Logo" %}" height="80" class="hide-theme-light logo">
|
||||
<div class="netbox-edition fw-semibold">{{ settings.RELEASE.edition }}</div>
|
||||
</div>
|
||||
|
||||
@ -81,7 +81,7 @@
|
||||
<div class="col">
|
||||
<a href="{{ backend.url }}" class="btn w-100">
|
||||
{% if backend.icon_name %}<i class="mdi mdi-{{ backend.icon_name }}"></i>
|
||||
{% elif backend.icon_img %}<img src="{{ backend.icon_img }}" height="24" {% if backend.display_name %}class="me-2" {% endif %}/>{% endif %}
|
||||
{% elif backend.icon_img %}<img src="{{ backend.icon_img }}" height="24"{% if backend.display_name %}class="me-2 sso-icon" {% endif %}/>{% endif %}
|
||||
{{ backend.display_name }}
|
||||
</a>
|
||||
</div>
|
||||
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
||||
Django==5.1.2
|
||||
django-cors-headers==4.4.0
|
||||
django-cors-headers==4.5.0
|
||||
django-debug-toolbar==4.4.6
|
||||
django-filter==24.3
|
||||
django-htmx==1.19.0
|
||||
@ -20,8 +20,8 @@ feedparser==6.0.11
|
||||
gunicorn==23.0.0
|
||||
Jinja2==3.1.4
|
||||
Markdown==3.7
|
||||
mkdocs-material==9.5.39
|
||||
mkdocstrings[python-legacy]==0.26.1
|
||||
mkdocs-material==9.5.41
|
||||
mkdocstrings[python-legacy]==0.26.2
|
||||
netaddr==1.3.0
|
||||
nh3==0.2.18
|
||||
Pillow==10.4.0
|
||||
@ -30,8 +30,8 @@ PyYAML==6.0.2
|
||||
requests==2.32.3
|
||||
social-auth-app-django==5.4.2
|
||||
social-auth-core==4.5.4
|
||||
strawberry-graphql==0.243.1
|
||||
strawberry-graphql==0.246.2
|
||||
strawberry-graphql-django==0.48.0
|
||||
svgwrite==1.4.3
|
||||
tablib==3.6.1
|
||||
tablib==3.7.0
|
||||
tzdata==2024.2
|
||||
|
@ -14,6 +14,11 @@ RED='\033[0;31m'
|
||||
YELLOW='\033[0;33m'
|
||||
NOCOLOR='\033[0m'
|
||||
|
||||
printf "${YELLOW}This script is obsolete and will be removed in a future release.\n"
|
||||
printf "Please use pre-commit instead:\n"
|
||||
printf " pip install pre-commit\n"
|
||||
printf " pre-commit install${NOCOLOR}\n"
|
||||
|
||||
if [ -d ./venv/ ]; then
|
||||
VENV="$PWD/venv"
|
||||
if [ -e $VENV/bin/python ]; then
|
||||
|
Loading…
Reference in New Issue
Block a user