diff --git a/.github/ISSUE_TEMPLATE/bug_report.yaml b/.github/ISSUE_TEMPLATE/bug_report.yaml index 2a1ecd5d06..318a9b7ad0 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yaml +++ b/.github/ISSUE_TEMPLATE/bug_report.yaml @@ -17,7 +17,7 @@ body: What version of NetBox are you currently running? (If you don't have access to the most recent NetBox release, consider testing on our [demo instance](https://demo.netbox.dev/) before opening a bug report to see if your issue has already been addressed.) - placeholder: v3.0.7 + placeholder: v3.0.8 validations: required: true - type: dropdown diff --git a/.github/ISSUE_TEMPLATE/feature_request.yaml b/.github/ISSUE_TEMPLATE/feature_request.yaml index 6a3f81e1ea..be89acfad9 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.yaml +++ b/.github/ISSUE_TEMPLATE/feature_request.yaml @@ -14,7 +14,7 @@ body: attributes: label: NetBox version description: What version of NetBox are you currently running? - placeholder: v3.0.7 + placeholder: v3.0.8 validations: required: true - type: dropdown diff --git a/docs/customization/custom-links.md b/docs/customization/custom-links.md deleted file mode 100644 index 1ee366cfd5..0000000000 --- a/docs/customization/custom-links.md +++ /dev/null @@ -1 +0,0 @@ -{!models/extras/customlink.md!} diff --git a/docs/release-notes/version-3.0.md b/docs/release-notes/version-3.0.md index 25295b6210..69d8b8456f 100644 --- a/docs/release-notes/version-3.0.md +++ b/docs/release-notes/version-3.0.md @@ -1,6 +1,27 @@ # NetBox v3.0 -## v3.0.8 (FUTURE) +## v3.0.9 (FUTURE) + +--- + +## v3.0.8 (2021-10-20) + +### Enhancements + +* [#7551](https://github.com/netbox-community/netbox/issues/7551) - Add UI field to filter interfaces by kind +* [#7561](https://github.com/netbox-community/netbox/issues/7561) - Add a utilization column to the IP ranges table + +### Bug Fixes + +* [#7300](https://github.com/netbox-community/netbox/issues/7300) - Fix incorrect Device LLDP interface row coloring +* [#7495](https://github.com/netbox-community/netbox/issues/7495) - Fix navigation UI issue that caused improper element overlap +* [#7529](https://github.com/netbox-community/netbox/issues/7529) - Restore horizontal scrolling for tables in narrow viewports +* [#7534](https://github.com/netbox-community/netbox/issues/7534) - Avoid exception when utilizing "create and add another" twice in succession +* [#7544](https://github.com/netbox-community/netbox/issues/7544) - Fix multi-value filtering of custom field objects +* [#7545](https://github.com/netbox-community/netbox/issues/7545) - Fix incorrect display of update/delete events for webhooks +* [#7550](https://github.com/netbox-community/netbox/issues/7550) - Fix rendering of UTF8-encoded data in change records +* [#7556](https://github.com/netbox-community/netbox/issues/7556) - Fix display of version when new release is available +* [#7584](https://github.com/netbox-community/netbox/issues/7584) - Fix alignment of object identifier under object view --- diff --git a/mkdocs.yml b/mkdocs.yml index 72750d6f51..ce660285fc 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -66,7 +66,7 @@ nav: - Customization: - Custom Fields: 'customization/custom-fields.md' - Custom Validation: 'customization/custom-validation.md' - - Custom Links: 'customization/custom-links.md' + - Custom Links: 'models/extras/customlink.md' - Export Templates: 'customization/export-templates.md' - Custom Scripts: 'customization/custom-scripts.md' - Reports: 'customization/reports.md' diff --git a/netbox/dcim/choices.py b/netbox/dcim/choices.py index a4c3cb983c..2a7ed8b898 100644 --- a/netbox/dcim/choices.py +++ b/netbox/dcim/choices.py @@ -704,6 +704,18 @@ class PowerOutletFeedLegChoices(ChoiceSet): # Interfaces # +class InterfaceKindChoices(ChoiceSet): + KIND_PHYSICAL = 'physical' + KIND_VIRTUAL = 'virtual' + KIND_WIRELESS = 'wireless' + + CHOICES = ( + (KIND_PHYSICAL, 'Physical'), + (KIND_VIRTUAL, 'Virtual'), + (KIND_WIRELESS, 'Wireless'), + ) + + class InterfaceTypeChoices(ChoiceSet): # Virtual diff --git a/netbox/dcim/forms/filtersets.py b/netbox/dcim/forms/filtersets.py index 501e78b18c..0ee08bc77d 100644 --- a/netbox/dcim/forms/filtersets.py +++ b/netbox/dcim/forms/filtersets.py @@ -7,7 +7,6 @@ from dcim.constants import * from dcim.models import * from extras.forms import CustomFieldModelFilterForm, LocalConfigContextFilterForm from tenancy.forms import TenancyFilterForm -from tenancy.models import Tenant from utilities.forms import ( APISelectMultiple, add_blank_choice, BootstrapMixin, ColorField, DynamicModelMultipleChoiceField, StaticSelect, StaticSelectMultiple, TagFilterField, BOOLEAN_WITH_BLANK_CHOICES, @@ -966,9 +965,14 @@ class InterfaceFilterForm(DeviceComponentFilterForm): model = Interface field_groups = [ ['q', 'tag'], - ['name', 'label', 'type', 'enabled', 'mgmt_only', 'mac_address', 'wwn'], + ['name', 'label', 'kind', 'type', 'enabled', 'mgmt_only', 'mac_address', 'wwn'], ['region_id', 'site_group_id', 'site_id', 'location_id', 'device_id'], ] + kind = forms.MultipleChoiceField( + choices=InterfaceKindChoices, + required=False, + widget=StaticSelectMultiple() + ) type = forms.MultipleChoiceField( choices=InterfaceTypeChoices, required=False, diff --git a/netbox/extras/filtersets.py b/netbox/extras/filtersets.py index 25fd32f0de..af8d904f4e 100644 --- a/netbox/extras/filtersets.py +++ b/netbox/extras/filtersets.py @@ -15,6 +15,7 @@ from .models import * __all__ = ( 'ConfigContextFilterSet', 'ContentTypeFilterSet', + 'CustomFieldFilterSet', 'CustomLinkFilterSet', 'ExportTemplateFilterSet', 'ImageAttachmentFilterSet', @@ -47,7 +48,7 @@ class WebhookFilterSet(BaseFilterSet): ] -class CustomFieldFilterSet(django_filters.FilterSet): +class CustomFieldFilterSet(BaseFilterSet): content_types = ContentTypeFilter() class Meta: diff --git a/netbox/ipam/tables/ip.py b/netbox/ipam/tables/ip.py index 485e4a1231..ddad6c5734 100644 --- a/netbox/ipam/tables/ip.py +++ b/netbox/ipam/tables/ip.py @@ -260,11 +260,16 @@ class IPRangeTable(BaseTable): linkify=True ) tenant = TenantColumn() + utilization = UtilizationColumn( + accessor='utilization', + orderable=False + ) class Meta(BaseTable.Meta): model = IPRange fields = ( 'pk', 'start_address', 'end_address', 'size', 'vrf', 'status', 'role', 'tenant', 'description', + 'utilization', ) default_columns = ( 'pk', 'start_address', 'end_address', 'size', 'vrf', 'status', 'role', 'tenant', 'description', diff --git a/netbox/netbox/settings.py b/netbox/netbox/settings.py index 3df9a855ac..35e0c6714c 100644 --- a/netbox/netbox/settings.py +++ b/netbox/netbox/settings.py @@ -16,7 +16,7 @@ from django.core.validators import URLValidator # Environment setup # -VERSION = '3.0.8-dev' +VERSION = '3.0.9-dev' # Hostname HOSTNAME = platform.node() diff --git a/netbox/netbox/views/__init__.py b/netbox/netbox/views/__init__.py index 3568204fef..2c033e7601 100644 --- a/netbox/netbox/views/__init__.py +++ b/netbox/netbox/views/__init__.py @@ -137,7 +137,7 @@ class HomeView(View): release_version, release_url = latest_release if release_version > version.parse(settings.VERSION): new_release = { - 'version': str(latest_release), + 'version': str(release_version), 'url': release_url, } diff --git a/netbox/netbox/views/generic.py b/netbox/netbox/views/generic.py index 4baf2e0e9f..75e978e2ab 100644 --- a/netbox/netbox/views/generic.py +++ b/netbox/netbox/views/generic.py @@ -282,11 +282,11 @@ class ObjectEditView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View): messages.success(request, mark_safe(msg)) if '_addanother' in request.POST: - redirect_url = request.get_full_path() + redirect_url = request.path # If the object has clone_fields, pre-populate a new instance of the form if hasattr(obj, 'clone_fields'): - redirect_url += f"{'&' if '?' in redirect_url else '?'}{prepare_cloned_fields(obj)}" + redirect_url += f"?{prepare_cloned_fields(obj)}" return redirect(redirect_url) diff --git a/netbox/project-static/dist/lldp.js b/netbox/project-static/dist/lldp.js index 7fac1012a9..2b3934742c 100644 --- a/netbox/project-static/dist/lldp.js +++ b/netbox/project-static/dist/lldp.js @@ -1,5 +1,5 @@ -(()=>{var gr=Object.create;var le=Object.defineProperty,_r=Object.defineProperties,Er=Object.getOwnPropertyDescriptor,vr=Object.getOwnPropertyDescriptors,yr=Object.getOwnPropertyNames,mn=Object.getOwnPropertySymbols,Tr=Object.getPrototypeOf,gn=Object.prototype.hasOwnProperty,br=Object.prototype.propertyIsEnumerable;var _n=(i,t,e)=>t in i?le(i,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):i[t]=e,O=(i,t)=>{for(var e in t||(t={}))gn.call(t,e)&&_n(i,e,t[e]);if(mn)for(var e of mn(t))br.call(t,e)&&_n(i,e,t[e]);return i},je=(i,t)=>_r(i,vr(t)),En=i=>le(i,"__esModule",{value:!0});var mt=(i,t)=>()=>(t||i((t={exports:{}}).exports,t),t.exports),Ar=(i,t)=>{En(i);for(var e in t)le(i,e,{get:t[e],enumerable:!0})},Sr=(i,t,e)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of yr(t))!gn.call(i,n)&&n!=="default"&&le(i,n,{get:()=>t[n],enumerable:!(e=Er(t,n))||e.enumerable});return i},vn=i=>Sr(En(le(i!=null?gr(Tr(i)):{},"default",i&&i.__esModule&&"default"in i?{get:()=>i.default,enumerable:!0}:{value:i,enumerable:!0})),i);var bi=(i,t,e)=>new Promise((n,o)=>{var r=u=>{try{l(e.next(u))}catch(p){o(p)}},s=u=>{try{l(e.throw(u))}catch(p){o(p)}},l=u=>u.done?n(u.value):Promise.resolve(u.value).then(r,s);l((e=e.apply(i,t)).next())});var on=mt((er,li)=>{(function(i,t){typeof define=="function"&&define.amd?define(t):typeof li=="object"&&li.exports?li.exports=t():i.EvEmitter=t()})(typeof window!="undefined"?window:er,function(){"use strict";function i(){}var t=i.prototype;return t.on=function(e,n){if(!(!e||!n)){var o=this._events=this._events||{},r=o[e]=o[e]||[];return r.indexOf(n)==-1&&r.push(n),this}},t.once=function(e,n){if(!(!e||!n)){this.on(e,n);var o=this._onceEvents=this._onceEvents||{},r=o[e]=o[e]||{};return r[n]=!0,this}},t.off=function(e,n){var o=this._events&&this._events[e];if(!(!o||!o.length)){var r=o.indexOf(n);return r!=-1&&o.splice(r,1),this}},t.emitEvent=function(e,n){var o=this._events&&this._events[e];if(!(!o||!o.length)){o=o.slice(0),n=n||[];for(var r=this._onceEvents&&this._onceEvents[e],s=0;s{(function(i,t){typeof define=="function"&&define.amd?define(t):typeof ci=="object"&&ci.exports?ci.exports=t():i.getSize=t()})(window,function(){"use strict";function t(d){var v=parseFloat(d),E=d.indexOf("%")==-1&&!isNaN(v);return E&&v}function e(){}var n=typeof console=="undefined"?e:function(d){console.error(d)},o=["paddingLeft","paddingRight","paddingTop","paddingBottom","marginLeft","marginRight","marginTop","marginBottom","borderLeftWidth","borderRightWidth","borderTopWidth","borderBottomWidth"],r=o.length;function s(){for(var d={width:0,height:0,innerWidth:0,innerHeight:0,outerWidth:0,outerHeight:0},v=0;v