checktheroads 4 лет назад
Родитель
Сommit
0479d5a02a

Разница между файлами не показана из-за своего большого размера
+ 0 - 0
netbox/project-static/dist/config.js


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
netbox/project-static/dist/config.js.map


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
netbox/project-static/dist/jobs.js


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
netbox/project-static/dist/jobs.js.map


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
netbox/project-static/dist/lldp.js


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
netbox/project-static/dist/lldp.js.map


Разница между файлами не показана из-за своего большого размера
+ 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.js


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
netbox/project-static/dist/netbox.js.map


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
netbox/project-static/dist/status.js


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
netbox/project-static/dist/status.js.map


+ 6 - 6
netbox/project-static/src/bs.ts

@@ -34,16 +34,16 @@ export function createToast(
   message: string,
   extra?: string,
 ): Toast {
-  let iconName = 'bi-exclamation-triangle-fill';
+  let iconName = 'mdi-alert';
   switch (level) {
     case 'warning':
-      iconName = 'bi-exclamation-triangle-fill';
+      iconName = 'mdi-alert';
     case 'success':
-      iconName = 'bi-check-circle-fill';
+      iconName = 'mdi-check-circle';
     case 'info':
-      iconName = 'bi-info-circle-fill';
+      iconName = 'mdi-information';
     case 'danger':
-      iconName = 'bi-exclamation-triangle-fill';
+      iconName = 'mdi-alert';
   }
 
   const container = document.createElement('div');
@@ -59,7 +59,7 @@ export function createToast(
   header.setAttribute('class', `toast-header bg-${level} text-body`);
 
   const icon = document.createElement('i');
-  icon.setAttribute('class', `bi ${iconName}`);
+  icon.setAttribute('class', `mdi ${iconName}`);
 
   const titleElement = document.createElement('strong');
   titleElement.setAttribute('class', 'me-auto ms-1');

+ 38 - 5
netbox/project-static/styles/netbox.scss

@@ -94,12 +94,37 @@
   margin-bottom: $spacer;
 }
 
+// Ensure elements with data-href set show the correct cursor.
+// data-href is set on non non-anchor elements that need to redirect the user to a URL when
+// clicked, but where an anchor element does not suffice or is not supported.
 *[data-href] {
   cursor: pointer;
 }
 
-// Use proper contrasting color foreground color for special components.
 @each $color, $value in $theme-colors {
+  // Override CSS values on each theme color.
+
+  // Use Bootstrap's method of coloring alert links to appropriately color close buttons within
+  // another colored element.
+  // See: https://github.com/twbs/bootstrap/blob/2bdbb42dcf6bfb99b5e9e5444d9e64589eb8c08f/scss/_alert.scss#L50-L52
+  // See: https://github.com/twbs/bootstrap/blob/2bdbb42dcf6bfb99b5e9e5444d9e64589eb8c08f/scss/_close.scss#L12
+  $shaded-color: shade-color(mix($value, color-contrast($value), abs($alert-color-scale)), 5%);
+  $btn-close-bg: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='#{$shaded-color}'><path d='M.293.293a1 1 0 011.414 0L8 6.586 14.293.293a1 1 0 111.414 1.414L9.414 8l6.293 6.293a1 1 0 01-1.414 1.414L8 9.414l-6.293 6.293a1 1 0 01-1.414-1.414L6.586 8 .293 1.707a1 1 0 010-1.414z'/></svg>");
+  .bg-#{$color} button.btn-close {
+    background: transparent escape-svg($btn-close-bg) center / $btn-close-width auto no-repeat;
+  }
+
+  // Use Bootstrap's method of coloring the .alert-link class automatically.
+  // See: https://github.com/twbs/bootstrap/blob/2bdbb42dcf6bfb99b5e9e5444d9e64589eb8c08f/scss/_alert.scss#L50-L52
+  .toast.bg-#{$color},
+  .alert.alert-#{$color} {
+    a {
+      color: $shaded-color;
+      font-weight: $font-weight-bold;
+    }
+  }
+
+  // Use proper contrasting color foreground color for special components.
   .badge,
   .toast,
   .progress-bar {
@@ -107,11 +132,11 @@
       color: color-contrast($value);
     }
   }
-  // Use proper foreground color in the alert body. Note: this is applied to a, p, & small because
+
+  // Use proper foreground color in the alert body. Note: this is applied to p, & small because
   // we *don't* want to override the h1-h6 colors for alerts, since those are set to a color
   // similar to the alert color.
   .alert.alert-#{$color} {
-    a,
     p,
     small {
       color: color-contrast($value);
@@ -926,8 +951,9 @@ div.card > div.card-header > div.table-controls {
   border-bottom: 1px solid $nav-tabs-border-color;
 }
 
-// Shade the home page content background-color.
-body {
+// Page-specific styles.
+html {
+  // Shade the home page content background-color.
   &[data-netbox-path='/'] {
     .content-container,
     .search {
@@ -940,4 +966,11 @@ body {
       }
     }
   }
+
+  // Don't show the django-messages toasts on the login screen in favor of the alert component.
+  &[data-netbox-path*='/login'] {
+    #django-messages {
+      display: none;
+    }
+  }
 }

+ 4 - 0
netbox/project-static/styles/theme-base.scss

@@ -128,6 +128,10 @@ $font-family-sans-serif: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMa
 $font-family-monospace: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono',
   'Courier New', monospace;
 
+// 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;
+
 $accordion-padding-y: 0.8125rem;
 $accordion-padding-x: 0.8125rem;
 

+ 1 - 7
netbox/project-static/styles/theme-dark.scss

@@ -46,6 +46,7 @@ $link-hover-color: $blue-100;
 // Alerts
 $alert-bg-scale: -5%;
 $alert-border-scale: -20%;
+$alert-color-scale: 20%;
 
 // Tables
 $table-color: $gray-100;
@@ -261,15 +262,8 @@ $carousel-dark-control-icon-filter: invert(1) grayscale(100);
 // Close
 $btn-close-color: $white;
 $btn-close-white-filter: invert(1) grayscale(100%) brightness(200%);
-
 $btn-close-bg: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='#{$btn-close-color}'><path d='M.293.293a1 1 0 011.414 0L8 6.586 14.293.293a1 1 0 111.414 1.414L9.414 8l6.293 6.293a1 1 0 01-1.414 1.414L8 9.414l-6.293 6.293a1 1 0 01-1.414-1.414L6.586 8 .293 1.707a1 1 0 010-1.414z'/></svg>");
 
-@each $color, $value in $theme-colors {
-  .bg-#{$color} button.btn-close {
-    background: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='#{color-contrast($value)}'><path d='M.293.293a1 1 0 011.414 0L8 6.586 14.293.293a1 1 0 111.414 1.414L9.414 8l6.293 6.293a1 1 0 01-1.414 1.414L8 9.414l-6.293 6.293a1 1 0 01-1.414-1.414L6.586 8 .293 1.707a1 1 0 010-1.414z'/></svg>");
-  }
-}
-
 // Code
 $code-color: $gray-200;
 $kbd-color: $white;

+ 41 - 21
netbox/templates/inc/messages.html

@@ -1,39 +1,59 @@
+{% load helpers %}
+
 <div id="django-messages" class="toast-container position-fixed bottom-0 end-0 m-3">
+  {# Django Messages #}
+
   {% if messages %}
     {% for message in messages %}
-    <div class="django-message toast align-items-center border-0 bg-{% if message.tags %}{{ message.tags }}{% else %}info{% endif %}" role="alert" aria-live="assertive" aria-atomic="true" data-bs-delay="10000">
-      <div class="d-flex">
-        <div class="toast-body">
-          {{ message }}
+      {% with message.level_tag|status_from_tag as status %}
+      {% with status|icon_from_status as icon %}
+        <div class="django-message toast align-items-center border-0 bg-{{ status }}" role="alert" aria-live="assertive" aria-atomic="true" data-bs-delay="10000">
+          <div class="d-flex">
+            <div class="toast-body">
+              <i class="mdi mdi-{{ icon }} me-1"></i>
+              {{ message }}
+            </div>
+            <button type="button" class="btn-close me-2 m-auto" data-bs-dismiss="toast" aria-label="Close"></button>
+          </div>
         </div>
-        <button type="button" class="btn-close me-2 m-auto" data-bs-dismiss="toast" aria-label="Close"></button>
-      </div>
-    </div>
+      {% endwith %}
+      {% endwith %}
     {% endfor %}
+
   {% elif form and form.non_field_errors %}
+    {# Non-Field Form Errors #}
+
     {% for error in form.non_field_errors.get_json_data %}
-    <div class="django-message toast align-items-center border-0 bg-danger" role="alert" aria-live="assertive" aria-atomic="true" data-bs-delay="10000">
-      <div class="d-flex">
-        <div class="toast-body">
-          {{ error.message }}
+      <div class="django-message toast align-items-center border-0 bg-danger" role="alert" aria-live="assertive" aria-atomic="true" data-bs-delay="10000">
+        <div class="d-flex">
+          <div class="toast-body">
+            <i class="mdi mdi-{{ "danger"|icon_from_status }} me-1"></i>
+            {{ error.message }}
+          </div>
+          <button type="button" class="btn-close me-2 m-auto" data-bs-dismiss="toast" aria-label="Close"></button>
         </div>
-        <button type="button" class="btn-close me-2 m-auto" data-bs-dismiss="toast" aria-label="Close"></button>
       </div>
-    </div>
     {% endfor %}
+  
   {% elif form and form.errors %}
+    {# Form Field Errors #}
+
     {% for field in form %}
       {% for error in field.errors %}
-      <div class="django-message toast align-items-center border-0 bg-danger" role="alert" aria-live="assertive" aria-atomic="true" data-bs-delay="60000">
-        <div class="toast-header bg-danger">
-          <strong class="me-auto">{{ field.label }}</strong>
-          <button type="button" class="btn-close me-2 m-auto" data-bs-dismiss="toast" aria-label="Close"></button>
+        <div class="django-message toast align-items-center border-0 bg-danger" role="alert" aria-live="assertive" aria-atomic="true" data-bs-delay="60000">
+          <div class="toast-header bg-danger">
+            <strong class="me-auto">
+              <i class="mdi mdi-{{ "danger"|icon_from_status }} me-1"></i>
+              {{ field.label }}
+            </strong>
+            <button type="button" class="btn-close me-2 m-auto" data-bs-dismiss="toast" aria-label="Close"></button>
+          </div>
+          <div class="toast-body">
+            {{ error|escape }}
+          </div>
         </div>
-        <div class="toast-body">
-          {{ error|escape }}
-        </div>
-      </div>
       {% endfor %}
     {% endfor %}
+
   {% endif %}
 </div>

+ 30 - 1
netbox/utilities/templatetags/helpers.py

@@ -326,6 +326,35 @@ def querystring(request, **kwargs):
         return ''
 
 
+@register.filter
+def status_from_tag(tag: str = "info") -> str:
+    """
+    Determine Bootstrap theme status/level from Django's Message.level_tag.
+    """
+    status_map = {
+        'warning': 'warning',
+        'success': 'success',
+        'error': 'danger',
+        'debug': 'info',
+        'info': 'info',
+    }
+    return status_map.get(tag.lower(), 'info')
+
+
+@register.filter
+def icon_from_status(status: str = "info") -> str:
+    """
+    Determine icon class name from Bootstrap theme status/level.
+    """
+    icon_map = {
+        'warning': 'alert',
+        'success': 'check-circle',
+        'danger': 'alert',
+        'info': 'information',
+    }
+    return icon_map.get(status.lower(), 'information')
+
+
 @register.inclusion_tag('utilities/templatetags/utilization_graph.html')
 def utilization_graph(utilization, warning_threshold=75, danger_threshold=90):
     """
@@ -338,7 +367,7 @@ def utilization_graph(utilization, warning_threshold=75, danger_threshold=90):
     elif warning_threshold or danger_threshold:
         bar_class = 'bg-success'
     else:
-        bar_class = 'bg-default'
+        bar_class = 'bg-gray'
     return {
         'utilization': utilization,
         'bar_class': bar_class,

Некоторые файлы не были показаны из-за большого количества измененных файлов