diff --git a/docs/configuration/optional-settings.md b/docs/configuration/optional-settings.md index fcebf7af6..110ca9322 100644 --- a/docs/configuration/optional-settings.md +++ b/docs/configuration/optional-settings.md @@ -161,16 +161,16 @@ EXEMPT_VIEW_PERMISSIONS = ['*'] Default: Empty dictionary -Some static choice fields on models can be configured with custom values. This is done by defining `FIELD_CHOICES` as a dictionary mapping model fields to their choices list. Each choice in the list must have a database value and a human-friendly label, and may optionally specify a color. +Some static choice fields on models can be configured with custom values. This is done by defining `FIELD_CHOICES` as a dictionary mapping model fields to their choices list. Each choice in the list must have a database value and a human-friendly label, and may optionally specify a color. (A list of available colors is provided below.) For example, to specify a custom set of choices for the site status field: ```python FIELD_CHOICES = { 'dcim.Site.status': ( - ('foo', 'Foo'), - ('bar', 'Bar'), - ('baz', 'Baz'), + ('foo', 'Foo', 'red'), + ('bar', 'Bar', 'green'), + ('baz', 'Baz', 'blue'), ) } ``` @@ -190,6 +190,22 @@ The following model field support configurable choices: * `ipam.VLAN.status` * `virtualization.VirtualMachine.status` +The following colors are supported: + +* `blue` +* `indigo` +* `purple` +* `pink` +* `red` +* `orange` +* `yellow` +* `green` +* `teal` +* `cyan` +* `gray` +* `black` +* `white` + --- ## HTTP_PROXIES diff --git a/docs/release-notes/version-3.1.md b/docs/release-notes/version-3.1.md index d50404261..2b8744032 100644 --- a/docs/release-notes/version-3.1.md +++ b/docs/release-notes/version-3.1.md @@ -6,6 +6,7 @@ * [#6782](https://github.com/netbox-community/netbox/issues/6782) - Enable the inclusion of custom links in tables * [#8100](https://github.com/netbox-community/netbox/issues/8100) - Add "other" choice for FHRP group protocol +* [#8175](https://github.com/netbox-community/netbox/issues/8175) - Display parent object when attaching an image ### Bug Fixes diff --git a/netbox/circuits/choices.py b/netbox/circuits/choices.py index 007b45298..fd58abb97 100644 --- a/netbox/circuits/choices.py +++ b/netbox/circuits/choices.py @@ -16,12 +16,12 @@ class CircuitStatusChoices(ChoiceSet): STATUS_DECOMMISSIONED = 'decommissioned' CHOICES = [ - (STATUS_PLANNED, 'Planned', 'info'), - (STATUS_PROVISIONING, 'Provisioning', 'primary'), - (STATUS_ACTIVE, 'Active', 'success'), - (STATUS_OFFLINE, 'Offline', 'danger'), - (STATUS_DEPROVISIONING, 'Deprovisioning', 'warning'), - (STATUS_DECOMMISSIONED, 'Decommissioned', 'secondary'), + (STATUS_PLANNED, 'Planned', 'cyan'), + (STATUS_PROVISIONING, 'Provisioning', 'blue'), + (STATUS_ACTIVE, 'Active', 'green'), + (STATUS_OFFLINE, 'Offline', 'red'), + (STATUS_DEPROVISIONING, 'Deprovisioning', 'yellow'), + (STATUS_DECOMMISSIONED, 'Decommissioned', 'gray'), ] diff --git a/netbox/dcim/choices.py b/netbox/dcim/choices.py index bcc926580..368ee1336 100644 --- a/netbox/dcim/choices.py +++ b/netbox/dcim/choices.py @@ -15,11 +15,11 @@ class SiteStatusChoices(ChoiceSet): STATUS_RETIRED = 'retired' CHOICES = [ - (STATUS_PLANNED, 'Planned', 'info'), - (STATUS_STAGING, 'Staging', 'primary'), - (STATUS_ACTIVE, 'Active', 'primary'), - (STATUS_DECOMMISSIONING, 'Decommissioning', 'warning'), - (STATUS_RETIRED, 'Retired', 'danger'), + (STATUS_PLANNED, 'Planned', 'cyan'), + (STATUS_STAGING, 'Staging', 'blue'), + (STATUS_ACTIVE, 'Active', 'green'), + (STATUS_DECOMMISSIONING, 'Decommissioning', 'yellow'), + (STATUS_RETIRED, 'Retired', 'red'), ] @@ -69,11 +69,11 @@ class RackStatusChoices(ChoiceSet): STATUS_DEPRECATED = 'deprecated' CHOICES = [ - (STATUS_RESERVED, 'Reserved', 'warning'), - (STATUS_AVAILABLE, 'Available', 'success'), - (STATUS_PLANNED, 'Planned', 'info'), - (STATUS_ACTIVE, 'Active', 'primary'), - (STATUS_DEPRECATED, 'Deprecated', 'danger'), + (STATUS_RESERVED, 'Reserved', 'yellow'), + (STATUS_AVAILABLE, 'Available', 'green'), + (STATUS_PLANNED, 'Planned', 'cyan'), + (STATUS_ACTIVE, 'Active', 'blue'), + (STATUS_DEPRECATED, 'Deprecated', 'red'), ] @@ -141,13 +141,13 @@ class DeviceStatusChoices(ChoiceSet): STATUS_DECOMMISSIONING = 'decommissioning' CHOICES = [ - (STATUS_OFFLINE, 'Offline', 'warning'), - (STATUS_ACTIVE, 'Active', 'success'), - (STATUS_PLANNED, 'Planned', 'info'), - (STATUS_STAGED, 'Staged', 'primary'), - (STATUS_FAILED, 'Failed', 'danger'), - (STATUS_INVENTORY, 'Inventory', 'secondary'), - (STATUS_DECOMMISSIONING, 'Decommissioning', 'warning'), + (STATUS_OFFLINE, 'Offline', 'gray'), + (STATUS_ACTIVE, 'Active', 'green'), + (STATUS_PLANNED, 'Planned', 'cyan'), + (STATUS_STAGED, 'Staged', 'blue'), + (STATUS_FAILED, 'Failed', 'red'), + (STATUS_INVENTORY, 'Inventory', 'purple'), + (STATUS_DECOMMISSIONING, 'Decommissioning', 'yellow'), ] @@ -1121,9 +1121,9 @@ class LinkStatusChoices(ChoiceSet): STATUS_DECOMMISSIONING = 'decommissioning' CHOICES = ( - (STATUS_CONNECTED, 'Connected', 'success'), - (STATUS_PLANNED, 'Planned', 'info'), - (STATUS_DECOMMISSIONING, 'Decommissioning', 'warning'), + (STATUS_CONNECTED, 'Connected', 'green'), + (STATUS_PLANNED, 'Planned', 'blue'), + (STATUS_DECOMMISSIONING, 'Decommissioning', 'yellow'), ) @@ -1162,10 +1162,10 @@ class PowerFeedStatusChoices(ChoiceSet): STATUS_FAILED = 'failed' CHOICES = [ - (STATUS_OFFLINE, 'Offline', 'warning'), - (STATUS_ACTIVE, 'Active', 'success'), - (STATUS_PLANNED, 'Planned', 'info'), - (STATUS_FAILED, 'Failed', 'danger'), + (STATUS_OFFLINE, 'Offline', 'gray'), + (STATUS_ACTIVE, 'Active', 'green'), + (STATUS_PLANNED, 'Planned', 'blue'), + (STATUS_FAILED, 'Failed', 'red'), ] @@ -1175,8 +1175,8 @@ class PowerFeedTypeChoices(ChoiceSet): TYPE_REDUNDANT = 'redundant' CHOICES = ( - (TYPE_PRIMARY, 'Primary', 'success'), - (TYPE_REDUNDANT, 'Redundant', 'info'), + (TYPE_PRIMARY, 'Primary', 'green'), + (TYPE_REDUNDANT, 'Redundant', 'cyan'), ) diff --git a/netbox/extras/choices.py b/netbox/extras/choices.py index ff117c4e5..c01e64831 100644 --- a/netbox/extras/choices.py +++ b/netbox/extras/choices.py @@ -91,9 +91,9 @@ class ObjectChangeActionChoices(ChoiceSet): ACTION_DELETE = 'delete' CHOICES = ( - (ACTION_CREATE, 'Created', 'success'), - (ACTION_UPDATE, 'Updated', 'primary'), - (ACTION_DELETE, 'Deleted', 'danger'), + (ACTION_CREATE, 'Created', 'green'), + (ACTION_UPDATE, 'Updated', 'blue'), + (ACTION_DELETE, 'Deleted', 'red'), ) @@ -109,10 +109,10 @@ class JournalEntryKindChoices(ChoiceSet): KIND_DANGER = 'danger' CHOICES = ( - (KIND_INFO, 'Info', 'info'), - (KIND_SUCCESS, 'Success', 'success'), - (KIND_WARNING, 'Warning', 'warning'), - (KIND_DANGER, 'Danger', 'danger'), + (KIND_INFO, 'Info', 'cyan'), + (KIND_SUCCESS, 'Success', 'green'), + (KIND_WARNING, 'Warning', 'yellow'), + (KIND_DANGER, 'Danger', 'red'), ) @@ -129,11 +129,11 @@ class LogLevelChoices(ChoiceSet): LOG_FAILURE = 'failure' CHOICES = ( - (LOG_DEFAULT, 'Default', 'secondary'), - (LOG_SUCCESS, 'Success', 'success'), - (LOG_INFO, 'Info', 'info'), - (LOG_WARNING, 'Warning', 'warning'), - (LOG_FAILURE, 'Failure', 'danger'), + (LOG_DEFAULT, 'Default', 'gray'), + (LOG_SUCCESS, 'Success', 'green'), + (LOG_INFO, 'Info', 'cyan'), + (LOG_WARNING, 'Warning', 'yellow'), + (LOG_FAILURE, 'Failure', 'red'), ) diff --git a/netbox/extras/views.py b/netbox/extras/views.py index 1660f8210..0df4d6905 100644 --- a/netbox/extras/views.py +++ b/netbox/extras/views.py @@ -473,6 +473,7 @@ class ObjectChangeLogView(View): class ImageAttachmentEditView(generic.ObjectEditView): queryset = ImageAttachment.objects.all() model_form = forms.ImageAttachmentForm + template_name = 'extras/imageattachment_edit.html' def alter_object(self, instance, request, args, kwargs): if not instance.pk: diff --git a/netbox/ipam/choices.py b/netbox/ipam/choices.py index 849f6a6bc..f9e4afffb 100644 --- a/netbox/ipam/choices.py +++ b/netbox/ipam/choices.py @@ -25,10 +25,10 @@ class PrefixStatusChoices(ChoiceSet): STATUS_DEPRECATED = 'deprecated' CHOICES = [ - (STATUS_CONTAINER, 'Container', 'secondary'), - (STATUS_ACTIVE, 'Active', 'primary'), - (STATUS_RESERVED, 'Reserved', 'info'), - (STATUS_DEPRECATED, 'Deprecated', 'danger'), + (STATUS_CONTAINER, 'Container', 'gray'), + (STATUS_ACTIVE, 'Active', 'blue'), + (STATUS_RESERVED, 'Reserved', 'cyan'), + (STATUS_DEPRECATED, 'Deprecated', 'red'), ] @@ -44,9 +44,9 @@ class IPRangeStatusChoices(ChoiceSet): STATUS_DEPRECATED = 'deprecated' CHOICES = [ - (STATUS_ACTIVE, 'Active', 'primary'), - (STATUS_RESERVED, 'Reserved', 'info'), - (STATUS_DEPRECATED, 'Deprecated', 'danger'), + (STATUS_ACTIVE, 'Active', 'blue'), + (STATUS_RESERVED, 'Reserved', 'cyan'), + (STATUS_DEPRECATED, 'Deprecated', 'red'), ] @@ -64,11 +64,11 @@ class IPAddressStatusChoices(ChoiceSet): STATUS_SLAAC = 'slaac' CHOICES = [ - (STATUS_ACTIVE, 'Active', 'primary'), - (STATUS_RESERVED, 'Reserved', 'info'), - (STATUS_DEPRECATED, 'Deprecated', 'danger'), - (STATUS_DHCP, 'DHCP', 'success'), - (STATUS_SLAAC, 'SLAAC', 'success'), + (STATUS_ACTIVE, 'Active', 'blue'), + (STATUS_RESERVED, 'Reserved', 'cyan'), + (STATUS_DEPRECATED, 'Deprecated', 'red'), + (STATUS_DHCP, 'DHCP', 'green'), + (STATUS_SLAAC, 'SLAAC', 'purple'), ] @@ -84,14 +84,14 @@ class IPAddressRoleChoices(ChoiceSet): ROLE_CARP = 'carp' CHOICES = ( - (ROLE_LOOPBACK, 'Loopback', 'secondary'), - (ROLE_SECONDARY, 'Secondary', 'primary'), - (ROLE_ANYCAST, 'Anycast', 'warning'), - (ROLE_VIP, 'VIP'), - (ROLE_VRRP, 'VRRP', 'success'), - (ROLE_HSRP, 'HSRP', 'success'), - (ROLE_GLBP, 'GLBP', 'success'), - (ROLE_CARP, 'CARP'), 'success', + (ROLE_LOOPBACK, 'Loopback', 'gray'), + (ROLE_SECONDARY, 'Secondary', 'blue'), + (ROLE_ANYCAST, 'Anycast', 'yellow'), + (ROLE_VIP, 'VIP', 'purple'), + (ROLE_VRRP, 'VRRP', 'green'), + (ROLE_HSRP, 'HSRP', 'green'), + (ROLE_GLBP, 'GLBP', 'green'), + (ROLE_CARP, 'CARP'), 'green', ) @@ -141,9 +141,9 @@ class VLANStatusChoices(ChoiceSet): STATUS_DEPRECATED = 'deprecated' CHOICES = [ - (STATUS_ACTIVE, 'Active', 'primary'), - (STATUS_RESERVED, 'Reserved', 'info'), - (STATUS_DEPRECATED, 'Deprecated', 'danger'), + (STATUS_ACTIVE, 'Active', 'blue'), + (STATUS_RESERVED, 'Reserved', 'cyan'), + (STATUS_DEPRECATED, 'Deprecated', 'red'), ] diff --git a/netbox/project-static/dist/netbox-dark.css b/netbox/project-static/dist/netbox-dark.css index e711685bf..fe89a1b48 100644 Binary files a/netbox/project-static/dist/netbox-dark.css and b/netbox/project-static/dist/netbox-dark.css differ diff --git a/netbox/project-static/dist/netbox-light.css b/netbox/project-static/dist/netbox-light.css index 10c15397d..f8e59ef99 100644 Binary files a/netbox/project-static/dist/netbox-light.css and b/netbox/project-static/dist/netbox-light.css differ diff --git a/netbox/project-static/dist/netbox-print.css b/netbox/project-static/dist/netbox-print.css index 4562597d8..9b46d50c8 100644 Binary files a/netbox/project-static/dist/netbox-print.css and b/netbox/project-static/dist/netbox-print.css differ diff --git a/netbox/project-static/styles/theme-base.scss b/netbox/project-static/styles/theme-base.scss index 26a1811bc..97f6dd020 100644 --- a/netbox/project-static/styles/theme-base.scss +++ b/netbox/project-static/styles/theme-base.scss @@ -33,95 +33,6 @@ $darkest: #171b1d; @import '../node_modules/bootstrap/scss/variables'; -// Make color palette colors available as theme colors. -// For example, you could use `.bg-red-100`, if needed. -$theme-color-addons: ( - 'darker': $darker, - 'darkest': $darkest, - 'gray': $gray-400, - 'gray-100': $gray-100, - 'gray-200': $gray-200, - 'gray-300': $gray-300, - 'gray-400': $gray-400, - 'gray-500': $gray-500, - 'gray-600': $gray-600, - 'gray-700': $gray-700, - 'gray-800': $gray-800, - 'gray-900': $gray-900, - 'red-100': $red-100, - 'red-200': $red-200, - 'red-300': $red-300, - 'red-400': $red-400, - 'red-500': $red-500, - 'red-600': $red-600, - 'red-700': $red-700, - 'red-800': $red-800, - 'red-900': $red-900, - 'yellow-100': $yellow-100, - 'yellow-200': $yellow-200, - 'yellow-300': $yellow-300, - 'yellow-400': $yellow-400, - 'yellow-500': $yellow-500, - 'yellow-600': $yellow-600, - 'yellow-700': $yellow-700, - 'yellow-800': $yellow-800, - 'yellow-900': $yellow-900, - 'green-100': $green-100, - 'green-200': $green-200, - 'green-300': $green-300, - 'green-400': $green-400, - 'green-500': $green-500, - 'green-600': $green-600, - 'green-700': $green-700, - 'green-800': $green-800, - 'green-900': $green-900, - 'blue-100': $blue-100, - 'blue-200': $blue-200, - 'blue-300': $blue-300, - 'blue-400': $blue-400, - 'blue-500': $blue-500, - 'blue-600': $blue-600, - 'blue-700': $blue-700, - 'blue-800': $blue-800, - 'blue-900': $blue-900, - 'cyan-100': $cyan-100, - 'cyan-200': $cyan-200, - 'cyan-300': $cyan-300, - 'cyan-400': $cyan-400, - 'cyan-500': $cyan-500, - 'cyan-600': $cyan-600, - 'cyan-700': $cyan-700, - 'cyan-800': $cyan-800, - 'cyan-900': $cyan-900, - 'indigo-100': $indigo-100, - 'indigo-200': $indigo-200, - 'indigo-300': $indigo-300, - 'indigo-400': $indigo-400, - 'indigo-500': $indigo-500, - 'indigo-600': $indigo-600, - 'indigo-700': $indigo-700, - 'indigo-800': $indigo-800, - 'indigo-900': $indigo-900, - 'purple-100': $purple-100, - 'purple-200': $purple-200, - 'purple-300': $purple-300, - 'purple-400': $purple-400, - 'purple-500': $purple-500, - 'purple-600': $purple-600, - 'purple-700': $purple-700, - 'purple-800': $purple-800, - 'purple-900': $purple-900, - 'pink-100': $pink-100, - 'pink-200': $pink-200, - 'pink-300': $pink-300, - 'pink-400': $pink-400, - 'pink-500': $pink-500, - 'pink-600': $pink-600, - 'pink-700': $pink-700, - 'pink-800': $pink-800, - 'pink-900': $pink-900, -); - // This is the same value as the default from Bootstrap, but it needs to be in scope prior to // importing _variables.scss from Bootstrap. $btn-close-width: 1em; diff --git a/netbox/project-static/styles/theme-dark.scss b/netbox/project-static/styles/theme-dark.scss index c5fb5dcf1..c787d38bf 100644 --- a/netbox/project-static/styles/theme-dark.scss +++ b/netbox/project-static/styles/theme-dark.scss @@ -3,6 +3,7 @@ @use 'sass:map'; @import './theme-base'; +// Theme colors (BS5 classes) $primary: $blue-300; $secondary: $gray-500; $success: $green-300; @@ -13,6 +14,7 @@ $light: $gray-300; $dark: $gray-500; $theme-colors: ( + // BS5 theme colors 'primary': $primary, 'secondary': $secondary, 'success': $success, @@ -21,18 +23,23 @@ $theme-colors: ( 'danger': $danger, 'light': $light, 'dark': $dark, - 'red': $red-300, - 'yellow': $yellow-300, - 'green': $green-300, + + // General-purpose palette 'blue': $blue-300, - 'cyan': $cyan-300, 'indigo': $indigo-300, 'purple': $purple-300, 'pink': $pink-300, + 'red': $red-300, + 'orange': $orange-300, + 'yellow': $yellow-300, + 'green': $green-300, + 'teal': $teal-300, + 'cyan': $cyan-300, + 'gray': $gray-300, + 'black': $black, + 'white': $white, ); -$theme-colors: map-merge($theme-colors, $theme-color-addons); - // Gradient $gradient: linear-gradient(180deg, rgba($white, 0.15), rgba($white, 0)); diff --git a/netbox/project-static/styles/theme-light.scss b/netbox/project-static/styles/theme-light.scss index c14f7f314..05ead54b5 100644 --- a/netbox/project-static/styles/theme-light.scss +++ b/netbox/project-static/styles/theme-light.scss @@ -4,22 +4,42 @@ $input-border-color: $gray-200; -$theme-colors: map-merge( - $theme-colors, - ( - 'primary': #337ab7, - 'red': $red-500, - 'yellow': $yellow-500, - 'green': $green-500, - 'blue': $blue-500, - 'cyan': $cyan-500, - 'indigo': $indigo-500, - 'purple': $purple-500, - 'pink': $pink-500, - ) -); +// Theme colors (BS5 classes) +$primary: #337ab7; +$secondary: $gray-600; +$success: $green-500; +$info: #54d6f0; +$warning: $yellow-500; +$danger: $red-500; +$light: $gray-200; +$dark: $gray-800; -$theme-colors: map-merge($theme-colors, $theme-color-addons); +$theme-colors: ( + // BS5 theme colors + 'primary': $primary, + 'secondary': $secondary, + 'success': $success, + 'info': $info, + 'warning': $warning, + 'danger': $danger, + 'light': $light, + 'dark': $dark, + + // General-purpose palette + 'blue': $blue-500, + 'indigo': $indigo-500, + 'purple': $purple-500, + 'pink': $pink-500, + 'red': $red-500, + 'orange': $orange-500, + 'yellow': $yellow-500, + 'green': $green-500, + 'teal': $teal-500, + 'cyan': $cyan-500, + 'gray': $gray-500, + 'black': $black, + 'white': $white, +); $light: $gray-200; diff --git a/netbox/templates/circuits/inc/circuit_termination.html b/netbox/templates/circuits/inc/circuit_termination.html index 5c224f7c0..89b7891a2 100644 --- a/netbox/templates/circuits/inc/circuit_termination.html +++ b/netbox/templates/circuits/inc/circuit_termination.html @@ -10,7 +10,7 @@ {% endif %} {% if termination and perms.circuits.change_circuittermination %} - + Edit diff --git a/netbox/templates/extras/imageattachment_edit.html b/netbox/templates/extras/imageattachment_edit.html new file mode 100644 index 000000000..cd7d40a8e --- /dev/null +++ b/netbox/templates/extras/imageattachment_edit.html @@ -0,0 +1,16 @@ +{% extends 'generic/object_edit.html' %} +{% load helpers %} + +{% block form_fields %} +
+ +
+ +
+
+ {{ block.super }} +{% endblock form_fields %} diff --git a/netbox/templates/inc/profile_button.html b/netbox/templates/inc/profile_button.html index 876ee31dc..230aa02ad 100644 --- a/netbox/templates/inc/profile_button.html +++ b/netbox/templates/inc/profile_button.html @@ -1,56 +1,56 @@ {% if request.user.is_authenticated %} - - - - + {% else %} -
- - Log In - - - -
+
+ + Log In + + + +
{% endif %} diff --git a/netbox/virtualization/choices.py b/netbox/virtualization/choices.py index 1aaaf6bf9..bb9220d09 100644 --- a/netbox/virtualization/choices.py +++ b/netbox/virtualization/choices.py @@ -16,10 +16,10 @@ class VirtualMachineStatusChoices(ChoiceSet): STATUS_DECOMMISSIONING = 'decommissioning' CHOICES = [ - (STATUS_OFFLINE, 'Offline', 'warning'), - (STATUS_ACTIVE, 'Active', 'success'), - (STATUS_PLANNED, 'Planned', 'info'), - (STATUS_STAGED, 'Staged', 'primary'), - (STATUS_FAILED, 'Failed', 'danger'), - (STATUS_DECOMMISSIONING, 'Decommissioning', 'warning'), + (STATUS_OFFLINE, 'Offline', 'gray'), + (STATUS_ACTIVE, 'Active', 'green'), + (STATUS_PLANNED, 'Planned', 'cyan'), + (STATUS_STAGED, 'Staged', 'blue'), + (STATUS_FAILED, 'Failed', 'red'), + (STATUS_DECOMMISSIONING, 'Decommissioning', 'yellow'), ]