فهرست منبع

Merge pull request #8179 from netbox-community/8089-choice-colors

Closes #8089: Color names
Jeremy Stretch 4 سال پیش
والد
کامیت
e0126d971c

+ 20 - 4
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

+ 1 - 0
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
 

+ 6 - 6
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'),
     ]
 
 

+ 26 - 26
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'),
     )
 
 

+ 12 - 12
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'),
     )
 
 

+ 1 - 0
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:

+ 23 - 23
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'),
     ]
 
 

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
netbox/project-static/dist/netbox-dark.css


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
netbox/project-static/dist/netbox-light.css


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
netbox/project-static/dist/netbox-print.css


+ 0 - 89
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;

+ 13 - 6
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));
 

+ 35 - 15
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;
 

+ 1 - 1
netbox/templates/circuits/inc/circuit_termination.html

@@ -10,7 +10,7 @@
                 </a>
             {% endif %}
             {% if termination and perms.circuits.change_circuittermination %}
-                <a href="{% url 'circuits:circuittermination_edit' pk=termination.pk %}" class="btn btn-sm btn-yellow lh-1">
+                <a href="{% url 'circuits:circuittermination_edit' pk=termination.pk %}" class="btn btn-sm btn-warning lh-1">
                     <span class="mdi mdi-pencil" aria-hidden="true"></span> Edit
                 </a>
                 <a href="{% url 'circuits:circuit_terminations_swap' pk=object.pk %}" class="btn btn-sm btn-primary lh-1">

+ 16 - 0
netbox/templates/extras/imageattachment_edit.html

@@ -0,0 +1,16 @@
+{% extends 'generic/object_edit.html' %}
+{% load helpers %}
+
+{% block form_fields %}
+  <div class="row mb-3">
+    <label class="col-sm-3 col-form-label text-lg-end required">
+      {{ obj.parent|meta:"verbose_name"|bettertitle }}
+    </label>
+    <div class="col-sm-9">
+      <div class="form-control-plaintext">
+        <a href="{{ obj.parent.get_absolute_url }}" class="">{{ obj.parent }}</a>
+      </div>
+    </div>
+  </div>
+  {{ block.super }}
+{% endblock form_fields %}

+ 53 - 53
netbox/templates/inc/profile_button.html

@@ -1,56 +1,56 @@
 {% if request.user.is_authenticated %}
-<span class="dropdown profile-button">
-  <button
-    type="button"
-    aria-expanded="false"
-    data-bs-toggle="dropdown"
-    class="btn btn-outline-secondary dropdown-toggle w-100"
-  >
-    <i class="mdi mdi-account"></i>
-    <span id="navbar_user">{{ request.user|truncatechars:"30" }}</span>
-  </button>
-  <ul class="dropdown-menu dropdown-menu-end">
-    <li>
-      <button type="button" class="dropdown-item color-mode-toggle">
-        <i class="color-mode-icon mdi mdi-lightbulb"></i>&nbsp;
-        <span class="color-mode-text">Dark Mode</span>
-      </button>
-    </li>
-    <li>
-      {% if request.user.is_staff %}
-      <a class="dropdown-item" href="{% url 'admin:index' %}">
-        <i class="mdi mdi-cog"></i> Admin
-      </a>
-      {% endif %}
-    </li>
-    <li>
-      <a class="dropdown-item" href="{% url 'user:profile' %}">
-        <i class="mdi mdi-account"></i> Profile & Settings
-      </a>
-    </li>
-    <li><hr class="dropdown-divider" /></li>
-    <li>
-      <a class="dropdown-item" href="{% url 'logout' %}">
-        <i class="mdi mdi-logout-variant"></i> Log Out
-      </a>
-    </li>
-  </ul>
-</span>
+  <div class="dropdown profile-button">
+    <button type="button" aria-expanded="false" data-bs-toggle="dropdown" class="btn btn-outline-secondary dropdown-toggle w-100">
+      <i class="mdi mdi-account"></i>
+      <span id="navbar_user">{{ request.user|truncatechars:"30" }}</span>
+    </button>
+    <ul class="dropdown-menu dropdown-menu-end">
+      <li>
+        <button type="button" class="dropdown-item color-mode-toggle">
+          <i class="color-mode-icon mdi mdi-lightbulb"></i>
+          <span class="color-mode-text">Dark Mode</span>
+        </button>
+      </li>
+      <li>
+        {% if request.user.is_staff %}
+          <a class="dropdown-item" href="{% url 'admin:index' %}">
+            <i class="mdi mdi-cog"></i> Admin
+          </a>
+        {% endif %}
+      </li>
+      <li>
+        <a class="dropdown-item" href="{% url 'user:profile' %}">
+          <i class="mdi mdi-account"></i> Profile
+        </a>
+      </li>
+      <li>
+        <a class="dropdown-item" href="{% url 'user:preferences' %}">
+          <i class="mdi mdi-wrench"></i> Preferences
+        </a>
+      </li>
+      <li><hr class="dropdown-divider" /></li>
+      <li>
+        <a class="dropdown-item" href="{% url 'logout' %}">
+          <i class="mdi mdi-logout-variant"></i> Log Out
+        </a>
+      </li>
+    </ul>
+  </div>
 {% else %}
-<div class="btn-group">
-  <a class="btn btn-primary ws-nowrap" type="button" href="{% url 'login' %}">
-    <i class="mdi mdi-login-variant"></i> Log In
-  </a>
-  <button type="button" class="btn btn-primary dropdown-toggle dropdown-toggle-split" data-bs-toggle="dropdown">
-    <span class="visually-hidden">Toggle Dropdown</span>
-  </button>
-  <ul class="dropdown-menu dropdown-menu-end">
-    <li>
-      <button class="dropdown-item color-mode-toggle">
-        <i class="color-mode-icon mdi mdi-lightbulb"></i>&nbsp;
-        <span class="color-mode-text">Dark Mode</span>
-      </button>
-    </li>
-  </ul>
-</div>
+  <div class="btn-group">
+    <a class="btn btn-primary ws-nowrap" type="button" href="{% url 'login' %}">
+      <i class="mdi mdi-login-variant"></i> Log In
+    </a>
+    <button type="button" class="btn btn-primary dropdown-toggle dropdown-toggle-split" data-bs-toggle="dropdown">
+      <span class="visually-hidden">Toggle Dropdown</span>
+    </button>
+    <ul class="dropdown-menu dropdown-menu-end">
+      <li>
+        <button class="dropdown-item color-mode-toggle">
+          <i class="color-mode-icon mdi mdi-lightbulb"></i>
+          <span class="color-mode-text">Dark Mode</span>
+        </button>
+      </li>
+    </ul>
+  </div>
 {% endif %}

+ 6 - 6
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'),
     ]

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است