Merge branch 'develop' into 3428-cache-invalidation

This commit is contained in:
John Anderson 2019-08-20 17:35:54 -04:00
commit 63c3f423c2
32 changed files with 992 additions and 688 deletions

View File

@ -3,12 +3,21 @@ v2.6.3 (FUTURE)
## Bug Fixes ## Bug Fixes
* [#3420](https://github.com/netbox-community/netbox/issues/3420) - Serial number filter for racks, devices, and inventory items is now case-insensitive * [#3420](https://github.com/netbox-community/netbox/issues/3420) - Serial number filter for racks, devices, and inventory items is now case-insensitive
<<<<<<< HEAD
* [#3428](https://github.com/netbox-community/netbox/issues/3420) - Fixed cache invalidation issues ([#3300](https://github.com/netbox-community/netbox/issues/3300), [#3363](https://github.com/netbox-community/netbox/issues/3363), [#3379](https://github.com/netbox-community/netbox/issues/3379), [#3382](https://github.com/netbox-community/netbox/issues/3382)) by switching to `prefetch_related()` instead of `select_related()` and removing use of `update()` * [#3428](https://github.com/netbox-community/netbox/issues/3420) - Fixed cache invalidation issues ([#3300](https://github.com/netbox-community/netbox/issues/3300), [#3363](https://github.com/netbox-community/netbox/issues/3363), [#3379](https://github.com/netbox-community/netbox/issues/3379), [#3382](https://github.com/netbox-community/netbox/issues/3382)) by switching to `prefetch_related()` instead of `select_related()` and removing use of `update()`
=======
* [#3421](https://github.com/netbox-community/netbox/issues/3421) - Fix exception when ordering power connections list by PDU
* [#3424](https://github.com/netbox-community/netbox/issues/3424) - Fix tag coloring for non-linked tags
* [#3426](https://github.com/netbox-community/netbox/issues/3426) - Improve API error handling for ChoiceFields
>>>>>>> develop
## Enhancements ## Enhancements
* [#3386](https://github.com/netbox-community/netbox/issues/3386) - Add `mac_address` filter for virtual machines
* [#3391](https://github.com/netbox-community/netbox/issues/3391) - Update Bootstrap CSS to v3.4.1
* [#3405](https://github.com/netbox-community/netbox/issues/3405) - Fix population of power port/outlet details on device creation * [#3405](https://github.com/netbox-community/netbox/issues/3405) - Fix population of power port/outlet details on device creation
* [#3422](https://github.com/netbox-community/netbox/issues/3422) - Prevent navigation menu from overlapping page content * [#3422](https://github.com/netbox-community/netbox/issues/3422) - Prevent navigation menu from overlapping page content
* [#3430](https://github.com/netbox-community/netbox/issues/3430) - Linkify platform field on device view
--- ---

View File

@ -729,6 +729,7 @@ class PowerConnectionTable(BaseTable):
viewname='dcim:device', viewname='dcim:device',
accessor=Accessor('connected_endpoint.device'), accessor=Accessor('connected_endpoint.device'),
args=[Accessor('connected_endpoint.device.pk')], args=[Accessor('connected_endpoint.device.pk')],
order_by='_connected_poweroutlet__device',
verbose_name='PDU' verbose_name='PDU'
) )
outlet = tables.Column( outlet = tables.Column(

View File

@ -5,6 +5,7 @@ import sys
from django import get_version from django import get_version
from django.apps import apps from django.apps import apps
from django.conf import settings from django.conf import settings
from django.contrib.auth.models import User
from django.core.management.base import BaseCommand from django.core.management.base import BaseCommand
APPS = ['circuits', 'dcim', 'extras', 'ipam', 'secrets', 'tenancy', 'users', 'virtualization'] APPS = ['circuits', 'dcim', 'extras', 'ipam', 'secrets', 'tenancy', 'users', 'virtualization']
@ -50,6 +51,9 @@ class Command(BaseCommand):
except KeyError: except KeyError:
pass pass
# Additional objects to include
namespace['User'] = User
# Load convenience commands # Load convenience commands
namespace.update({ namespace.update({
'lsmodels': self._lsmodels, 'lsmodels': self._lsmodels,

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

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

@ -1,6 +1,6 @@
/*! /*!
* Bootstrap v3.3.7 (http://getbootstrap.com) * Bootstrap v3.4.1 (https://getbootstrap.com/)
* Copyright 2011-2016 Twitter, Inc. * Copyright 2011-2019 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
*/ */
.btn-default, .btn-default,
@ -9,9 +9,9 @@
.btn-info, .btn-info,
.btn-warning, .btn-warning,
.btn-danger { .btn-danger {
text-shadow: 0 -1px 0 rgba(0, 0, 0, .2); text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075); -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);
} }
.btn-default:active, .btn-default:active,
.btn-primary:active, .btn-primary:active,
@ -25,8 +25,8 @@
.btn-info.active, .btn-info.active,
.btn-warning.active, .btn-warning.active,
.btn-danger.active { .btn-danger.active {
-webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
} }
.btn-default.disabled, .btn-default.disabled,
.btn-primary.disabled, .btn-primary.disabled,
@ -62,7 +62,6 @@ fieldset[disabled] .btn-danger {
background-image: none; background-image: none;
} }
.btn-default { .btn-default {
text-shadow: 0 1px 0 #fff;
background-image: -webkit-linear-gradient(top, #fff 0%, #e0e0e0 100%); background-image: -webkit-linear-gradient(top, #fff 0%, #e0e0e0 100%);
background-image: -o-linear-gradient(top, #fff 0%, #e0e0e0 100%); background-image: -o-linear-gradient(top, #fff 0%, #e0e0e0 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#e0e0e0)); background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#e0e0e0));
@ -71,6 +70,7 @@ fieldset[disabled] .btn-danger {
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
background-repeat: repeat-x; background-repeat: repeat-x;
border-color: #dbdbdb; border-color: #dbdbdb;
text-shadow: 0 1px 0 #fff;
border-color: #ccc; border-color: #ccc;
} }
.btn-default:hover, .btn-default:hover,
@ -311,41 +311,41 @@ fieldset[disabled] .btn-danger.active {
} }
.thumbnail, .thumbnail,
.img-thumbnail { .img-thumbnail {
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075); -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);
box-shadow: 0 1px 2px rgba(0, 0, 0, .075); box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);
} }
.dropdown-menu > li > a:hover, .dropdown-menu > li > a:hover,
.dropdown-menu > li > a:focus { .dropdown-menu > li > a:focus {
background-color: #e8e8e8;
background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8)); background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8));
background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%); background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);
background-repeat: repeat-x; background-repeat: repeat-x;
background-color: #e8e8e8;
} }
.dropdown-menu > .active > a, .dropdown-menu > .active > a,
.dropdown-menu > .active > a:hover, .dropdown-menu > .active > a:hover,
.dropdown-menu > .active > a:focus { .dropdown-menu > .active > a:focus {
background-color: #2e6da4;
background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%); background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%); background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4)); background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4));
background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%); background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);
background-repeat: repeat-x; background-repeat: repeat-x;
background-color: #2e6da4;
} }
.navbar-default { .navbar-default {
background-image: -webkit-linear-gradient(top, #fff 0%, #f8f8f8 100%); background-image: -webkit-linear-gradient(top, #ffffff 0%, #f8f8f8 100%);
background-image: -o-linear-gradient(top, #fff 0%, #f8f8f8 100%); background-image: -o-linear-gradient(top, #ffffff 0%, #f8f8f8 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#f8f8f8)); background-image: -webkit-gradient(linear, left top, left bottom, from(#ffffff), to(#f8f8f8));
background-image: linear-gradient(to bottom, #fff 0%, #f8f8f8 100%); background-image: linear-gradient(to bottom, #ffffff 0%, #f8f8f8 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
background-repeat: repeat-x; background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
border-radius: 4px; border-radius: 4px;
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075); -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075);
} }
.navbar-default .navbar-nav > .open > a, .navbar-default .navbar-nav > .open > a,
.navbar-default .navbar-nav > .active > a { .navbar-default .navbar-nav > .active > a {
@ -355,12 +355,12 @@ fieldset[disabled] .btn-danger.active {
background-image: linear-gradient(to bottom, #dbdbdb 0%, #e2e2e2 100%); background-image: linear-gradient(to bottom, #dbdbdb 0%, #e2e2e2 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0);
background-repeat: repeat-x; background-repeat: repeat-x;
-webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075); -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.075);
box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075); box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.075);
} }
.navbar-brand, .navbar-brand,
.navbar-nav > li > a { .navbar-nav > li > a {
text-shadow: 0 1px 0 rgba(255, 255, 255, .25); text-shadow: 0 1px 0 rgba(255, 255, 255, 0.25);
} }
.navbar-inverse { .navbar-inverse {
background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222 100%); background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222 100%);
@ -368,8 +368,8 @@ fieldset[disabled] .btn-danger.active {
background-image: -webkit-gradient(linear, left top, left bottom, from(#3c3c3c), to(#222)); background-image: -webkit-gradient(linear, left top, left bottom, from(#3c3c3c), to(#222));
background-image: linear-gradient(to bottom, #3c3c3c 0%, #222 100%); background-image: linear-gradient(to bottom, #3c3c3c 0%, #222 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
background-repeat: repeat-x; background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
border-radius: 4px; border-radius: 4px;
} }
.navbar-inverse .navbar-nav > .open > a, .navbar-inverse .navbar-nav > .open > a,
@ -380,12 +380,12 @@ fieldset[disabled] .btn-danger.active {
background-image: linear-gradient(to bottom, #080808 0%, #0f0f0f 100%); background-image: linear-gradient(to bottom, #080808 0%, #0f0f0f 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0);
background-repeat: repeat-x; background-repeat: repeat-x;
-webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25); -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.25);
box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25); box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.25);
} }
.navbar-inverse .navbar-brand, .navbar-inverse .navbar-brand,
.navbar-inverse .navbar-nav > li > a { .navbar-inverse .navbar-nav > li > a {
text-shadow: 0 -1px 0 rgba(0, 0, 0, .25); text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
} }
.navbar-static-top, .navbar-static-top,
.navbar-fixed-top, .navbar-fixed-top,
@ -406,9 +406,9 @@ fieldset[disabled] .btn-danger.active {
} }
} }
.alert { .alert {
text-shadow: 0 1px 0 rgba(255, 255, 255, .2); text-shadow: 0 1px 0 rgba(255, 255, 255, 0.2);
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05); -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05);
} }
.alert-success { .alert-success {
background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%); background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);
@ -495,14 +495,14 @@ fieldset[disabled] .btn-danger.active {
background-repeat: repeat-x; background-repeat: repeat-x;
} }
.progress-bar-striped { .progress-bar-striped {
background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
} }
.list-group { .list-group {
border-radius: 4px; border-radius: 4px;
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075); -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);
box-shadow: 0 1px 2px rgba(0, 0, 0, .075); box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);
} }
.list-group-item.active, .list-group-item.active,
.list-group-item.active:hover, .list-group-item.active:hover,
@ -522,8 +522,8 @@ fieldset[disabled] .btn-danger.active {
text-shadow: none; text-shadow: none;
} }
.panel { .panel {
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .05); -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
box-shadow: 0 1px 2px rgba(0, 0, 0, .05); box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
} }
.panel-default > .panel-heading { .panel-default > .panel-heading {
background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
@ -581,7 +581,7 @@ fieldset[disabled] .btn-danger.active {
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);
background-repeat: repeat-x; background-repeat: repeat-x;
border-color: #dcdcdc; border-color: #dcdcdc;
-webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1); -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1);
box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1); box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1);
} }
/*# sourceMappingURL=bootstrap-theme.css.map */ /*# sourceMappingURL=bootstrap-theme.css.map */

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

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,6 +1,6 @@
/*! /*!
* Bootstrap v3.3.7 (http://getbootstrap.com) * Bootstrap v3.4.1 (https://getbootstrap.com/)
* Copyright 2011-2016 Twitter, Inc. * Copyright 2011-2019 Twitter, Inc.
* Licensed under the MIT license * Licensed under the MIT license
*/ */
@ -17,10 +17,10 @@ if (typeof jQuery === 'undefined') {
}(jQuery); }(jQuery);
/* ======================================================================== /* ========================================================================
* Bootstrap: transition.js v3.3.7 * Bootstrap: transition.js v3.4.1
* http://getbootstrap.com/javascript/#transitions * https://getbootstrap.com/docs/3.4/javascript/#transitions
* ======================================================================== * ========================================================================
* Copyright 2011-2016 Twitter, Inc. * Copyright 2011-2019 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* ======================================================================== */ * ======================================================================== */
@ -28,7 +28,7 @@ if (typeof jQuery === 'undefined') {
+function ($) { +function ($) {
'use strict'; 'use strict';
// CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/) // CSS TRANSITION SUPPORT (Shoutout: https://modernizr.com/)
// ============================================================ // ============================================================
function transitionEnd() { function transitionEnd() {
@ -50,7 +50,7 @@ if (typeof jQuery === 'undefined') {
return false // explicit for ie8 ( ._.) return false // explicit for ie8 ( ._.)
} }
// http://blog.alexmaccaw.com/css-transitions // https://blog.alexmaccaw.com/css-transitions
$.fn.emulateTransitionEnd = function (duration) { $.fn.emulateTransitionEnd = function (duration) {
var called = false var called = false
var $el = this var $el = this
@ -77,10 +77,10 @@ if (typeof jQuery === 'undefined') {
}(jQuery); }(jQuery);
/* ======================================================================== /* ========================================================================
* Bootstrap: alert.js v3.3.7 * Bootstrap: alert.js v3.4.1
* http://getbootstrap.com/javascript/#alerts * https://getbootstrap.com/docs/3.4/javascript/#alerts
* ======================================================================== * ========================================================================
* Copyright 2011-2016 Twitter, Inc. * Copyright 2011-2019 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* ======================================================================== */ * ======================================================================== */
@ -96,7 +96,7 @@ if (typeof jQuery === 'undefined') {
$(el).on('click', dismiss, this.close) $(el).on('click', dismiss, this.close)
} }
Alert.VERSION = '3.3.7' Alert.VERSION = '3.4.1'
Alert.TRANSITION_DURATION = 150 Alert.TRANSITION_DURATION = 150
@ -109,7 +109,8 @@ if (typeof jQuery === 'undefined') {
selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7 selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
} }
var $parent = $(selector === '#' ? [] : selector) selector = selector === '#' ? [] : selector
var $parent = $(document).find(selector)
if (e) e.preventDefault() if (e) e.preventDefault()
@ -172,10 +173,10 @@ if (typeof jQuery === 'undefined') {
}(jQuery); }(jQuery);
/* ======================================================================== /* ========================================================================
* Bootstrap: button.js v3.3.7 * Bootstrap: button.js v3.4.1
* http://getbootstrap.com/javascript/#buttons * https://getbootstrap.com/docs/3.4/javascript/#buttons
* ======================================================================== * ========================================================================
* Copyright 2011-2016 Twitter, Inc. * Copyright 2011-2019 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* ======================================================================== */ * ======================================================================== */
@ -192,7 +193,7 @@ if (typeof jQuery === 'undefined') {
this.isLoading = false this.isLoading = false
} }
Button.VERSION = '3.3.7' Button.VERSION = '3.4.1'
Button.DEFAULTS = { Button.DEFAULTS = {
loadingText: 'loading...' loadingText: 'loading...'
@ -298,10 +299,10 @@ if (typeof jQuery === 'undefined') {
}(jQuery); }(jQuery);
/* ======================================================================== /* ========================================================================
* Bootstrap: carousel.js v3.3.7 * Bootstrap: carousel.js v3.4.1
* http://getbootstrap.com/javascript/#carousel * https://getbootstrap.com/docs/3.4/javascript/#carousel
* ======================================================================== * ========================================================================
* Copyright 2011-2016 Twitter, Inc. * Copyright 2011-2019 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* ======================================================================== */ * ======================================================================== */
@ -329,7 +330,7 @@ if (typeof jQuery === 'undefined') {
.on('mouseleave.bs.carousel', $.proxy(this.cycle, this)) .on('mouseleave.bs.carousel', $.proxy(this.cycle, this))
} }
Carousel.VERSION = '3.3.7' Carousel.VERSION = '3.4.1'
Carousel.TRANSITION_DURATION = 600 Carousel.TRANSITION_DURATION = 600
@ -443,7 +444,9 @@ if (typeof jQuery === 'undefined') {
var slidEvent = $.Event('slid.bs.carousel', { relatedTarget: relatedTarget, direction: direction }) // yes, "slid" var slidEvent = $.Event('slid.bs.carousel', { relatedTarget: relatedTarget, direction: direction }) // yes, "slid"
if ($.support.transition && this.$element.hasClass('slide')) { if ($.support.transition && this.$element.hasClass('slide')) {
$next.addClass(type) $next.addClass(type)
if (typeof $next === 'object' && $next.length) {
$next[0].offsetWidth // force reflow $next[0].offsetWidth // force reflow
}
$active.addClass(direction) $active.addClass(direction)
$next.addClass(direction) $next.addClass(direction)
$active $active
@ -505,10 +508,17 @@ if (typeof jQuery === 'undefined') {
// ================= // =================
var clickHandler = function (e) { var clickHandler = function (e) {
var href
var $this = $(this) var $this = $(this)
var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) // strip for ie7 var href = $this.attr('href')
if (href) {
href = href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7
}
var target = $this.attr('data-target') || href
var $target = $(document).find(target)
if (!$target.hasClass('carousel')) return if (!$target.hasClass('carousel')) return
var options = $.extend({}, $target.data(), $this.data()) var options = $.extend({}, $target.data(), $this.data())
var slideIndex = $this.attr('data-slide-to') var slideIndex = $this.attr('data-slide-to')
if (slideIndex) options.interval = false if (slideIndex) options.interval = false
@ -536,10 +546,10 @@ if (typeof jQuery === 'undefined') {
}(jQuery); }(jQuery);
/* ======================================================================== /* ========================================================================
* Bootstrap: collapse.js v3.3.7 * Bootstrap: collapse.js v3.4.1
* http://getbootstrap.com/javascript/#collapse * https://getbootstrap.com/docs/3.4/javascript/#collapse
* ======================================================================== * ========================================================================
* Copyright 2011-2016 Twitter, Inc. * Copyright 2011-2019 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* ======================================================================== */ * ======================================================================== */
@ -567,7 +577,7 @@ if (typeof jQuery === 'undefined') {
if (this.options.toggle) this.toggle() if (this.options.toggle) this.toggle()
} }
Collapse.VERSION = '3.3.7' Collapse.VERSION = '3.4.1'
Collapse.TRANSITION_DURATION = 350 Collapse.TRANSITION_DURATION = 350
@ -674,7 +684,7 @@ if (typeof jQuery === 'undefined') {
} }
Collapse.prototype.getParent = function () { Collapse.prototype.getParent = function () {
return $(this.options.parent) return $(document).find(this.options.parent)
.find('[data-toggle="collapse"][data-parent="' + this.options.parent + '"]') .find('[data-toggle="collapse"][data-parent="' + this.options.parent + '"]')
.each($.proxy(function (i, element) { .each($.proxy(function (i, element) {
var $element = $(element) var $element = $(element)
@ -697,7 +707,7 @@ if (typeof jQuery === 'undefined') {
var target = $trigger.attr('data-target') var target = $trigger.attr('data-target')
|| (href = $trigger.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7 || (href = $trigger.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7
return $(target) return $(document).find(target)
} }
@ -749,10 +759,10 @@ if (typeof jQuery === 'undefined') {
}(jQuery); }(jQuery);
/* ======================================================================== /* ========================================================================
* Bootstrap: dropdown.js v3.3.7 * Bootstrap: dropdown.js v3.4.1
* http://getbootstrap.com/javascript/#dropdowns * https://getbootstrap.com/docs/3.4/javascript/#dropdowns
* ======================================================================== * ========================================================================
* Copyright 2011-2016 Twitter, Inc. * Copyright 2011-2019 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* ======================================================================== */ * ======================================================================== */
@ -769,7 +779,7 @@ if (typeof jQuery === 'undefined') {
$(element).on('click.bs.dropdown', this.toggle) $(element).on('click.bs.dropdown', this.toggle)
} }
Dropdown.VERSION = '3.3.7' Dropdown.VERSION = '3.4.1'
function getParent($this) { function getParent($this) {
var selector = $this.attr('data-target') var selector = $this.attr('data-target')
@ -779,7 +789,7 @@ if (typeof jQuery === 'undefined') {
selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7 selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
} }
var $parent = selector && $(selector) var $parent = selector !== '#' ? $(document).find(selector) : null
return $parent && $parent.length ? $parent : $this.parent() return $parent && $parent.length ? $parent : $this.parent()
} }
@ -915,10 +925,10 @@ if (typeof jQuery === 'undefined') {
}(jQuery); }(jQuery);
/* ======================================================================== /* ========================================================================
* Bootstrap: modal.js v3.3.7 * Bootstrap: modal.js v3.4.1
* http://getbootstrap.com/javascript/#modals * https://getbootstrap.com/docs/3.4/javascript/#modals
* ======================================================================== * ========================================================================
* Copyright 2011-2016 Twitter, Inc. * Copyright 2011-2019 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* ======================================================================== */ * ======================================================================== */
@ -939,6 +949,7 @@ if (typeof jQuery === 'undefined') {
this.originalBodyPad = null this.originalBodyPad = null
this.scrollbarWidth = 0 this.scrollbarWidth = 0
this.ignoreBackdropClick = false this.ignoreBackdropClick = false
this.fixedContent = '.navbar-fixed-top, .navbar-fixed-bottom'
if (this.options.remote) { if (this.options.remote) {
this.$element this.$element
@ -949,7 +960,7 @@ if (typeof jQuery === 'undefined') {
} }
} }
Modal.VERSION = '3.3.7' Modal.VERSION = '3.4.1'
Modal.TRANSITION_DURATION = 300 Modal.TRANSITION_DURATION = 300
Modal.BACKDROP_TRANSITION_DURATION = 150 Modal.BACKDROP_TRANSITION_DURATION = 150
@ -1185,11 +1196,26 @@ if (typeof jQuery === 'undefined') {
Modal.prototype.setScrollbar = function () { Modal.prototype.setScrollbar = function () {
var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10) var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10)
this.originalBodyPad = document.body.style.paddingRight || '' this.originalBodyPad = document.body.style.paddingRight || ''
if (this.bodyIsOverflowing) this.$body.css('padding-right', bodyPad + this.scrollbarWidth) var scrollbarWidth = this.scrollbarWidth
if (this.bodyIsOverflowing) {
this.$body.css('padding-right', bodyPad + scrollbarWidth)
$(this.fixedContent).each(function (index, element) {
var actualPadding = element.style.paddingRight
var calculatedPadding = $(element).css('padding-right')
$(element)
.data('padding-right', actualPadding)
.css('padding-right', parseFloat(calculatedPadding) + scrollbarWidth + 'px')
})
}
} }
Modal.prototype.resetScrollbar = function () { Modal.prototype.resetScrollbar = function () {
this.$body.css('padding-right', this.originalBodyPad) this.$body.css('padding-right', this.originalBodyPad)
$(this.fixedContent).each(function (index, element) {
var padding = $(element).data('padding-right')
$(element).removeData('padding-right')
element.style.paddingRight = padding ? padding : ''
})
} }
Modal.prototype.measureScrollbar = function () { // thx walsh Modal.prototype.measureScrollbar = function () { // thx walsh
@ -1238,7 +1264,10 @@ if (typeof jQuery === 'undefined') {
$(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) { $(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) {
var $this = $(this) var $this = $(this)
var href = $this.attr('href') var href = $this.attr('href')
var $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) // strip for ie7 var target = $this.attr('data-target') ||
(href && href.replace(/.*(?=#[^\s]+$)/, '')) // strip for ie7
var $target = $(document).find(target)
var option = $target.data('bs.modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data()) var option = $target.data('bs.modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data())
if ($this.is('a')) e.preventDefault() if ($this.is('a')) e.preventDefault()
@ -1255,18 +1284,148 @@ if (typeof jQuery === 'undefined') {
}(jQuery); }(jQuery);
/* ======================================================================== /* ========================================================================
* Bootstrap: tooltip.js v3.3.7 * Bootstrap: tooltip.js v3.4.1
* http://getbootstrap.com/javascript/#tooltip * https://getbootstrap.com/docs/3.4/javascript/#tooltip
* Inspired by the original jQuery.tipsy by Jason Frame * Inspired by the original jQuery.tipsy by Jason Frame
* ======================================================================== * ========================================================================
* Copyright 2011-2016 Twitter, Inc. * Copyright 2011-2019 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* ======================================================================== */ * ======================================================================== */
+function ($) { +function ($) {
'use strict'; 'use strict';
var DISALLOWED_ATTRIBUTES = ['sanitize', 'whiteList', 'sanitizeFn']
var uriAttrs = [
'background',
'cite',
'href',
'itemtype',
'longdesc',
'poster',
'src',
'xlink:href'
]
var ARIA_ATTRIBUTE_PATTERN = /^aria-[\w-]*$/i
var DefaultWhitelist = {
// Global attributes allowed on any supplied element below.
'*': ['class', 'dir', 'id', 'lang', 'role', ARIA_ATTRIBUTE_PATTERN],
a: ['target', 'href', 'title', 'rel'],
area: [],
b: [],
br: [],
col: [],
code: [],
div: [],
em: [],
hr: [],
h1: [],
h2: [],
h3: [],
h4: [],
h5: [],
h6: [],
i: [],
img: ['src', 'alt', 'title', 'width', 'height'],
li: [],
ol: [],
p: [],
pre: [],
s: [],
small: [],
span: [],
sub: [],
sup: [],
strong: [],
u: [],
ul: []
}
/**
* A pattern that recognizes a commonly useful subset of URLs that are safe.
*
* Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts
*/
var SAFE_URL_PATTERN = /^(?:(?:https?|mailto|ftp|tel|file):|[^&:/?#]*(?:[/?#]|$))/gi
/**
* A pattern that matches safe data URLs. Only matches image, video and audio types.
*
* Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts
*/
var DATA_URL_PATTERN = /^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[a-z0-9+/]+=*$/i
function allowedAttribute(attr, allowedAttributeList) {
var attrName = attr.nodeName.toLowerCase()
if ($.inArray(attrName, allowedAttributeList) !== -1) {
if ($.inArray(attrName, uriAttrs) !== -1) {
return Boolean(attr.nodeValue.match(SAFE_URL_PATTERN) || attr.nodeValue.match(DATA_URL_PATTERN))
}
return true
}
var regExp = $(allowedAttributeList).filter(function (index, value) {
return value instanceof RegExp
})
// Check if a regular expression validates the attribute.
for (var i = 0, l = regExp.length; i < l; i++) {
if (attrName.match(regExp[i])) {
return true
}
}
return false
}
function sanitizeHtml(unsafeHtml, whiteList, sanitizeFn) {
if (unsafeHtml.length === 0) {
return unsafeHtml
}
if (sanitizeFn && typeof sanitizeFn === 'function') {
return sanitizeFn(unsafeHtml)
}
// IE 8 and below don't support createHTMLDocument
if (!document.implementation || !document.implementation.createHTMLDocument) {
return unsafeHtml
}
var createdDocument = document.implementation.createHTMLDocument('sanitization')
createdDocument.body.innerHTML = unsafeHtml
var whitelistKeys = $.map(whiteList, function (el, i) { return i })
var elements = $(createdDocument.body).find('*')
for (var i = 0, len = elements.length; i < len; i++) {
var el = elements[i]
var elName = el.nodeName.toLowerCase()
if ($.inArray(elName, whitelistKeys) === -1) {
el.parentNode.removeChild(el)
continue
}
var attributeList = $.map(el.attributes, function (el) { return el })
var whitelistedAttributes = [].concat(whiteList['*'] || [], whiteList[elName] || [])
for (var j = 0, len2 = attributeList.length; j < len2; j++) {
if (!allowedAttribute(attributeList[j], whitelistedAttributes)) {
el.removeAttribute(attributeList[j].nodeName)
}
}
}
return createdDocument.body.innerHTML
}
// TOOLTIP PUBLIC CLASS DEFINITION // TOOLTIP PUBLIC CLASS DEFINITION
// =============================== // ===============================
@ -1282,7 +1441,7 @@ if (typeof jQuery === 'undefined') {
this.init('tooltip', element, options) this.init('tooltip', element, options)
} }
Tooltip.VERSION = '3.3.7' Tooltip.VERSION = '3.4.1'
Tooltip.TRANSITION_DURATION = 150 Tooltip.TRANSITION_DURATION = 150
@ -1299,7 +1458,10 @@ if (typeof jQuery === 'undefined') {
viewport: { viewport: {
selector: 'body', selector: 'body',
padding: 0 padding: 0
} },
sanitize : true,
sanitizeFn : null,
whiteList : DefaultWhitelist
} }
Tooltip.prototype.init = function (type, element, options) { Tooltip.prototype.init = function (type, element, options) {
@ -1307,7 +1469,7 @@ if (typeof jQuery === 'undefined') {
this.type = type this.type = type
this.$element = $(element) this.$element = $(element)
this.options = this.getOptions(options) this.options = this.getOptions(options)
this.$viewport = this.options.viewport && $($.isFunction(this.options.viewport) ? this.options.viewport.call(this, this.$element) : (this.options.viewport.selector || this.options.viewport)) this.$viewport = this.options.viewport && $(document).find($.isFunction(this.options.viewport) ? this.options.viewport.call(this, this.$element) : (this.options.viewport.selector || this.options.viewport))
this.inState = { click: false, hover: false, focus: false } this.inState = { click: false, hover: false, focus: false }
if (this.$element[0] instanceof document.constructor && !this.options.selector) { if (this.$element[0] instanceof document.constructor && !this.options.selector) {
@ -1340,7 +1502,15 @@ if (typeof jQuery === 'undefined') {
} }
Tooltip.prototype.getOptions = function (options) { Tooltip.prototype.getOptions = function (options) {
options = $.extend({}, this.getDefaults(), this.$element.data(), options) var dataAttributes = this.$element.data()
for (var dataAttr in dataAttributes) {
if (dataAttributes.hasOwnProperty(dataAttr) && $.inArray(dataAttr, DISALLOWED_ATTRIBUTES) !== -1) {
delete dataAttributes[dataAttr]
}
}
options = $.extend({}, this.getDefaults(), dataAttributes, options)
if (options.delay && typeof options.delay == 'number') { if (options.delay && typeof options.delay == 'number') {
options.delay = { options.delay = {
@ -1349,6 +1519,10 @@ if (typeof jQuery === 'undefined') {
} }
} }
if (options.sanitize) {
options.template = sanitizeHtml(options.template, options.whiteList, options.sanitizeFn)
}
return options return options
} }
@ -1460,7 +1634,7 @@ if (typeof jQuery === 'undefined') {
.addClass(placement) .addClass(placement)
.data('bs.' + this.type, this) .data('bs.' + this.type, this)
this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element) this.options.container ? $tip.appendTo($(document).find(this.options.container)) : $tip.insertAfter(this.$element)
this.$element.trigger('inserted.bs.' + this.type) this.$element.trigger('inserted.bs.' + this.type)
var pos = this.getPosition() var pos = this.getPosition()
@ -1562,7 +1736,16 @@ if (typeof jQuery === 'undefined') {
var $tip = this.tip() var $tip = this.tip()
var title = this.getTitle() var title = this.getTitle()
$tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title) if (this.options.html) {
if (this.options.sanitize) {
title = sanitizeHtml(title, this.options.whiteList, this.options.sanitizeFn)
}
$tip.find('.tooltip-inner').html(title)
} else {
$tip.find('.tooltip-inner').text(title)
}
$tip.removeClass('fade in top bottom left right') $tip.removeClass('fade in top bottom left right')
} }
@ -1743,6 +1926,9 @@ if (typeof jQuery === 'undefined') {
}) })
} }
Tooltip.prototype.sanitizeHtml = function (unsafeHtml) {
return sanitizeHtml(unsafeHtml, this.options.whiteList, this.options.sanitizeFn)
}
// TOOLTIP PLUGIN DEFINITION // TOOLTIP PLUGIN DEFINITION
// ========================= // =========================
@ -1776,10 +1962,10 @@ if (typeof jQuery === 'undefined') {
}(jQuery); }(jQuery);
/* ======================================================================== /* ========================================================================
* Bootstrap: popover.js v3.3.7 * Bootstrap: popover.js v3.4.1
* http://getbootstrap.com/javascript/#popovers * https://getbootstrap.com/docs/3.4/javascript/#popovers
* ======================================================================== * ========================================================================
* Copyright 2011-2016 Twitter, Inc. * Copyright 2011-2019 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* ======================================================================== */ * ======================================================================== */
@ -1796,7 +1982,7 @@ if (typeof jQuery === 'undefined') {
if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js') if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js')
Popover.VERSION = '3.3.7' Popover.VERSION = '3.4.1'
Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, { Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, {
placement: 'right', placement: 'right',
@ -1822,10 +2008,25 @@ if (typeof jQuery === 'undefined') {
var title = this.getTitle() var title = this.getTitle()
var content = this.getContent() var content = this.getContent()
$tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title) if (this.options.html) {
$tip.find('.popover-content').children().detach().end()[ // we use append for html objects to maintain js events var typeContent = typeof content
this.options.html ? (typeof content == 'string' ? 'html' : 'append') : 'text'
if (this.options.sanitize) {
title = this.sanitizeHtml(title)
if (typeContent === 'string') {
content = this.sanitizeHtml(content)
}
}
$tip.find('.popover-title').html(title)
$tip.find('.popover-content').children().detach().end()[
typeContent === 'string' ? 'html' : 'append'
](content) ](content)
} else {
$tip.find('.popover-title').text(title)
$tip.find('.popover-content').children().detach().end().text(content)
}
$tip.removeClass('fade top bottom left right in') $tip.removeClass('fade top bottom left right in')
@ -1885,10 +2086,10 @@ if (typeof jQuery === 'undefined') {
}(jQuery); }(jQuery);
/* ======================================================================== /* ========================================================================
* Bootstrap: scrollspy.js v3.3.7 * Bootstrap: scrollspy.js v3.4.1
* http://getbootstrap.com/javascript/#scrollspy * https://getbootstrap.com/docs/3.4/javascript/#scrollspy
* ======================================================================== * ========================================================================
* Copyright 2011-2016 Twitter, Inc. * Copyright 2011-2019 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* ======================================================================== */ * ======================================================================== */
@ -1914,7 +2115,7 @@ if (typeof jQuery === 'undefined') {
this.process() this.process()
} }
ScrollSpy.VERSION = '3.3.7' ScrollSpy.VERSION = '3.4.1'
ScrollSpy.DEFAULTS = { ScrollSpy.DEFAULTS = {
offset: 10 offset: 10
@ -2058,10 +2259,10 @@ if (typeof jQuery === 'undefined') {
}(jQuery); }(jQuery);
/* ======================================================================== /* ========================================================================
* Bootstrap: tab.js v3.3.7 * Bootstrap: tab.js v3.4.1
* http://getbootstrap.com/javascript/#tabs * https://getbootstrap.com/docs/3.4/javascript/#tabs
* ======================================================================== * ========================================================================
* Copyright 2011-2016 Twitter, Inc. * Copyright 2011-2019 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* ======================================================================== */ * ======================================================================== */
@ -2078,7 +2279,7 @@ if (typeof jQuery === 'undefined') {
// jscs:enable requireDollarBeforejQueryAssignment // jscs:enable requireDollarBeforejQueryAssignment
} }
Tab.VERSION = '3.3.7' Tab.VERSION = '3.4.1'
Tab.TRANSITION_DURATION = 150 Tab.TRANSITION_DURATION = 150
@ -2107,7 +2308,7 @@ if (typeof jQuery === 'undefined') {
if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) return if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) return
var $target = $(selector) var $target = $(document).find(selector)
this.activate($this.closest('li'), $ul) this.activate($this.closest('li'), $ul)
this.activate($target, $target.parent(), function () { this.activate($target, $target.parent(), function () {
@ -2214,10 +2415,10 @@ if (typeof jQuery === 'undefined') {
}(jQuery); }(jQuery);
/* ======================================================================== /* ========================================================================
* Bootstrap: affix.js v3.3.7 * Bootstrap: affix.js v3.4.1
* http://getbootstrap.com/javascript/#affix * https://getbootstrap.com/docs/3.4/javascript/#affix
* ======================================================================== * ========================================================================
* Copyright 2011-2016 Twitter, Inc. * Copyright 2011-2019 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* ======================================================================== */ * ======================================================================== */
@ -2231,7 +2432,9 @@ if (typeof jQuery === 'undefined') {
var Affix = function (element, options) { var Affix = function (element, options) {
this.options = $.extend({}, Affix.DEFAULTS, options) this.options = $.extend({}, Affix.DEFAULTS, options)
this.$target = $(this.options.target) var target = this.options.target === Affix.DEFAULTS.target ? $(this.options.target) : $(document).find(this.options.target)
this.$target = target
.on('scroll.bs.affix.data-api', $.proxy(this.checkPosition, this)) .on('scroll.bs.affix.data-api', $.proxy(this.checkPosition, this))
.on('click.bs.affix.data-api', $.proxy(this.checkPositionWithEventLoop, this)) .on('click.bs.affix.data-api', $.proxy(this.checkPositionWithEventLoop, this))
@ -2243,7 +2446,7 @@ if (typeof jQuery === 'undefined') {
this.checkPosition() this.checkPosition()
} }
Affix.VERSION = '3.3.7' Affix.VERSION = '3.4.1'
Affix.RESET = 'affix affix-top affix-bottom' Affix.RESET = 'affix affix-top affix-bottom'

File diff suppressed because one or more lines are too long

View File

@ -4,7 +4,7 @@
<head> <head>
<title>Server Error</title> <title>Server Error</title>
<link rel="stylesheet" href="{% static 'bootstrap-3.3.7-dist/css/bootstrap.min.css' %}"> <link rel="stylesheet" href="{% static 'bootstrap-3.4.1-dist/css/bootstrap.min.css' %}">
<link rel="stylesheet" href="{% static 'font-awesome-4.7.0/css/font-awesome.min.css' %}"> <link rel="stylesheet" href="{% static 'font-awesome-4.7.0/css/font-awesome.min.css' %}">
<meta charset="UTF-8"> <meta charset="UTF-8">
</head> </head>

View File

@ -4,7 +4,7 @@
<html lang="en"> <html lang="en">
<head> <head>
<title>{% block title %}Home{% endblock %} - NetBox</title> <title>{% block title %}Home{% endblock %} - NetBox</title>
<link rel="stylesheet" href="{% static 'bootstrap-3.3.7-dist/css/bootstrap.min.css' %}"> <link rel="stylesheet" href="{% static 'bootstrap-3.4.1-dist/css/bootstrap.min.css' %}">
<link rel="stylesheet" href="{% static 'font-awesome-4.7.0/css/font-awesome.min.css' %}"> <link rel="stylesheet" href="{% static 'font-awesome-4.7.0/css/font-awesome.min.css' %}">
<link rel="stylesheet" href="{% static 'jquery-ui-1.12.1/jquery-ui.css' %}"> <link rel="stylesheet" href="{% static 'jquery-ui-1.12.1/jquery-ui.css' %}">
<link rel="stylesheet" href="{% static 'select2-4.0.5/css/select2.min.css' %}"> <link rel="stylesheet" href="{% static 'select2-4.0.5/css/select2.min.css' %}">
@ -67,7 +67,7 @@
</footer> </footer>
<script src="{% static 'js/jquery-3.3.1.min.js' %}"></script> <script src="{% static 'js/jquery-3.3.1.min.js' %}"></script>
<script src="{% static 'jquery-ui-1.12.1/jquery-ui.min.js' %}"></script> <script src="{% static 'jquery-ui-1.12.1/jquery-ui.min.js' %}"></script>
<script src="{% static 'bootstrap-3.3.7-dist/js/bootstrap.min.js' %}"></script> <script src="{% static 'bootstrap-3.4.1-dist/js/bootstrap.min.js' %}"></script>
<script src="{% static 'select2-4.0.5/js/select2.min.js' %}"></script> <script src="{% static 'select2-4.0.5/js/select2.min.js' %}"></script>
<script src="{% static 'clipboard-2.0.4.min.js' %}"></script> <script src="{% static 'clipboard-2.0.4.min.js' %}"></script>
<script src="{% static 'js/forms.js' %}?v{{ settings.VERSION }}"></script> <script src="{% static 'js/forms.js' %}?v{{ settings.VERSION }}"></script>

View File

@ -239,7 +239,7 @@
<td>Platform</td> <td>Platform</td>
<td> <td>
{% if device.platform %} {% if device.platform %}
<span>{{ device.platform }}</span> <a href="{{ device.platform.get_absolute_url }}">{{ device.platform }}</a>
{% else %} {% else %}
<span class="text-muted">None</span> <span class="text-muted">None</span>
{% endif %} {% endif %}

View File

@ -1,7 +1,5 @@
{% load helpers %} {% load helpers %}
{% if url_name %} {% if url_name %}<a href="{% url url_name %}?tag={{ tag.slug }}">{% endif %}
<a href="{% url url_name %}?tag={{ tag.slug }}"><span class="label label-default" style="color: {{ tag.color|fgcolor }}; background-color: #{{ tag.color }}">{{ tag }}</span></a> <span class="label label-default" style="color: {{ tag.color|fgcolor }}; background-color: #{{ tag.color }}">{{ tag }}</span>
{% else %} {% if url_name %}</a>{% endif %}
<span class="label label-default">{{ tag }}</span>
{% endif %}

View File

@ -85,9 +85,9 @@ class ChoiceField(Field):
def to_internal_value(self, data): def to_internal_value(self, data):
# Provide an explicit error message if the request is trying to write a dict # Provide an explicit error message if the request is trying to write a dict or list
if type(data) is dict: if isinstance(data, (dict, list)):
raise ValidationError('Value must be passed directly (e.g. "foo": 123); do not use a dictionary.') raise ValidationError('Value must be passed directly (e.g. "foo": 123); do not use a dictionary or list.')
# Check for string representations of boolean/integer values # Check for string representations of boolean/integer values
if hasattr(data, 'lower'): if hasattr(data, 'lower'):
@ -101,10 +101,13 @@ class ChoiceField(Field):
except ValueError: except ValueError:
pass pass
if data not in self._choices: try:
raise ValidationError("{} is not a valid choice.".format(data)) if data in self._choices:
return data return data
except TypeError: # Input is an unhashable type
pass
raise ValidationError("{} is not a valid choice.".format(data))
@property @property
def choices(self): def choices(self):

View File

@ -6,7 +6,9 @@ from netaddr.core import AddrFormatError
from dcim.models import DeviceRole, Interface, Platform, Region, Site from dcim.models import DeviceRole, Interface, Platform, Region, Site
from extras.filters import CustomFieldFilterSet from extras.filters import CustomFieldFilterSet
from tenancy.filtersets import TenancyFilterSet from tenancy.filtersets import TenancyFilterSet
from utilities.filters import NameSlugSearchFilterSet, NumericInFilter, TagFilter, TreeNodeMultipleChoiceFilter from utilities.filters import (
MultiValueMACAddressFilter, NameSlugSearchFilterSet, NumericInFilter, TagFilter, TreeNodeMultipleChoiceFilter,
)
from .constants import VM_STATUS_CHOICES from .constants import VM_STATUS_CHOICES
from .models import Cluster, ClusterGroup, ClusterType, VirtualMachine from .models import Cluster, ClusterGroup, ClusterType, VirtualMachine
@ -160,6 +162,10 @@ class VirtualMachineFilter(TenancyFilterSet, CustomFieldFilterSet):
to_field_name='slug', to_field_name='slug',
label='Platform (slug)', label='Platform (slug)',
) )
mac_address = MultiValueMACAddressFilter(
field_name='interfaces__mac_address',
label='MAC address',
)
tag = TagFilter() tag = TagFilter()
class Meta: class Meta:

View File

@ -525,7 +525,7 @@ class VirtualMachineFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFil
model = VirtualMachine model = VirtualMachine
field_order = [ field_order = [
'q', 'cluster_group', 'cluster_type', 'cluster_id', 'status', 'role', 'region', 'site', 'tenant_group', 'q', 'cluster_group', 'cluster_type', 'cluster_id', 'status', 'role', 'region', 'site', 'tenant_group',
'tenant', 'platform', 'tenant', 'platform', 'mac_address',
] ]
q = forms.CharField( q = forms.CharField(
required=False, required=False,
@ -606,6 +606,10 @@ class VirtualMachineFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFil
null_option=True, null_option=True,
) )
) )
mac_address = forms.CharField(
required=False,
label='MAC address'
)
# #