Jeremy Stretch vor 3 Monaten
Ursprung
Commit
1acd567706

+ 13 - 0
netbox/dcim/ui/panels.py

@@ -44,3 +44,16 @@ class DeviceManagementPanel(ObjectPanel):
         label=_('Out-of-band IP'),
         label=_('Out-of-band IP'),
         template_name='dcim/device/attrs/ipaddress.html',
         template_name='dcim/device/attrs/ipaddress.html',
     )
     )
+
+
+class SitePanel(ObjectPanel):
+    region = attrs.NestedObjectAttr('region', label=_('Region'), linkify=True)
+    group = attrs.NestedObjectAttr('group', label=_('Group'), linkify=True)
+    status = attrs.ChoiceAttr('status', label=_('Status'))
+    tenant = attrs.ObjectAttr('tenant', label=_('Tenant'), linkify=True, grouped_by='group')
+    facility = attrs.TextAttr('facility', label=_('Facility'))
+    description = attrs.TextAttr('description', label=_('Description'))
+    timezone = attrs.TimezoneAttr('time_zone', label=_('Timezone'))
+    physical_address = attrs.AddressAttr('physical_address', label=_('Physical address'), map_url=True)
+    shipping_address = attrs.AddressAttr('shipping_address', label=_('Shipping address'), map_url=True)
+    gps_coordinates = attrs.GPSCoordinatesAttr()

+ 1 - 0
netbox/dcim/views.py

@@ -465,6 +465,7 @@ class SiteView(GetRelatedModelsMixin, generic.ObjectView):
 
 
     def get_extra_context(self, request, instance):
     def get_extra_context(self, request, instance):
         return {
         return {
+            'site_panel': panels.SitePanel(instance, _('Site')),
             'related_models': self.get_related_models(
             'related_models': self.get_related_models(
                 request,
                 request,
                 instance,
                 instance,

+ 38 - 0
netbox/netbox/ui/attrs.py

@@ -123,6 +123,30 @@ class NestedObjectAttr(Attr):
         })
         })
 
 
 
 
+class AddressAttr(Attr):
+    template_name = 'components/attrs/address.html'
+
+    def __init__(self, *args, map_url=True, **kwargs):
+        super().__init__(*args, **kwargs)
+        if map_url is True:
+            self.map_url = get_config().MAPS_URL
+        elif map_url:
+            self.map_url = map_url
+        else:
+            self.map_url = None
+
+    def render(self, obj, context=None):
+        context = context or {}
+        value = self._resolve_attr(obj, self.accessor)
+        if value in (None, ''):
+            return self.placeholder
+        return render_to_string(self.template_name, {
+            **context,
+            'value': value,
+            'map_url': self.map_url,
+        })
+
+
 class GPSCoordinatesAttr(Attr):
 class GPSCoordinatesAttr(Attr):
     template_name = 'components/attrs/gps_coordinates.html'
     template_name = 'components/attrs/gps_coordinates.html'
 
 
@@ -152,6 +176,20 @@ class GPSCoordinatesAttr(Attr):
         })
         })
 
 
 
 
+class TimezoneAttr(Attr):
+    template_name = 'components/attrs/timezone.html'
+
+    def render(self, obj, context=None):
+        context = context or {}
+        value = self._resolve_attr(obj, self.accessor)
+        if value in (None, ''):
+            return self.placeholder
+        return render_to_string(self.template_name, {
+            **context,
+            'value': value,
+        })
+
+
 class TemplatedAttr(Attr):
 class TemplatedAttr(Attr):
 
 
     def __init__(self, *args, context=None, **kwargs):
     def __init__(self, *args, context=None, **kwargs):

+ 8 - 0
netbox/templates/components/attrs/address.html

@@ -0,0 +1,8 @@
+{% load i18n %}
+{% load l10n %}
+<span>{{ value|linebreaksbr }}</span>
+{% if map_url %}
+  <a href="{{ map_url }}{{ value }}" target="_blank" class="btn btn-primary btn-sm print-none">
+    <i class="mdi mdi-map-marker"></i> {% trans "Map" %}
+  </a>
+{% endif %}

+ 6 - 0
netbox/templates/components/attrs/timezone.html

@@ -0,0 +1,6 @@
+{% load i18n %}
+{% load tz %}
+<div>
+  {{ value }} ({% trans "UTC" %} {{ value|tzoffset }})<br />
+  <small class="text-muted">{% trans "Local time" %}: {% timezone value %}{% now 'Y-m-d H:i' %}{% endtimezone %}</small>
+</div>

+ 6 - 90
netbox/templates/dcim/site.html

@@ -24,100 +24,16 @@
 {% block content %}
 {% block content %}
 <div class="row">
 <div class="row">
 	<div class="col col-12 col-md-6">
 	<div class="col col-12 col-md-6">
-    <div class="card">
-      <h2 class="card-header">{% trans "Site" %}</h2>
-      <table class="table table-hover attr-table">
-        <tr>
-          <th scope="row">{% trans "Region" %}</th>
-          <td>
-            {% nested_tree object.region %}
-          </td>
-        </tr>
-        <tr>
-          <th scope="row">{% trans "Group" %}</th>
-          <td>
-            {% nested_tree object.group %}
-          </td>
-        </tr>
-        <tr>
-          <th scope="row">{% trans "Status" %}</th>
-          <td>{% badge object.get_status_display bg_color=object.get_status_color %}</td>
-        </tr>
-        <tr>
-          <th scope="row">{% trans "Tenant" %}</th>
-          <td>
-            {% if object.tenant.group %}
-              {{ object.tenant.group|linkify }} /
-            {% endif %}
-            {{ object.tenant|linkify|placeholder }}
-          </td>
-        </tr>
-        <tr>
-          <th scope="row">{% trans "Facility" %}</th>
-          <td>{{ object.facility|placeholder }}</td>
-        </tr>
-        <tr>
-          <th scope="row">{% trans "Description" %}</th>
-          <td>{{ object.description|placeholder }}</td>
-        </tr>
-        <tr>
-          <th scope="row">{% trans "Time Zone" %}</th>
-          <td>
-            {% if object.time_zone %}
-              {{ object.time_zone }} ({% trans "UTC" %} {{ object.time_zone|tzoffset }})<br />
-              <small class="text-muted">{% trans "Site time" %}: {% timezone object.time_zone %}{% now 'Y-m-d H:i' %}{% endtimezone %}</small>
-            {% else %}
-              {{ ''|placeholder }}
-            {% endif %}
-          </td>
-        </tr>
-        <tr>
-          <th scope="row">{% trans "Physical Address" %}</th>
-          <td class="d-flex justify-content-between align-items-start">
-            {% if object.physical_address %}
-              <span>{{ object.physical_address|linebreaksbr }}</span>
-              {% if config.MAPS_URL %}
-                <a href="{{ config.MAPS_URL }}{{ object.physical_address|urlencode }}" target="_blank" class="btn btn-primary btn-sm d-print-none">
-                  <i class="mdi mdi-map-marker"></i> {% trans "Map" %}
-                </a>
-              {% endif %}
-            {% else %}
-              {{ ''|placeholder }}
-            {% endif %}
-          </td>
-        </tr>
-        <tr>
-          <th scope="row">{% trans "Shipping Address" %}</th>
-          <td>{{ object.shipping_address|linebreaksbr|placeholder }}</td>
-        </tr>
-        <tr>
-          <th scope="row">{% trans "GPS Coordinates" %}</th>
-          <td class="position-relative">
-            {% if object.latitude and object.longitude %}
-              {% if config.MAPS_URL %}
-                <div class="position-absolute top-50 end-0 me-2 translate-middle-y d-print-none">
-                  <a href="{{ config.MAPS_URL }}{{ object.latitude|unlocalize }},{{ object.longitude|unlocalize }}" target="_blank" class="btn btn-primary btn-sm">
-                    <i class="mdi mdi-map-marker"></i> {% trans "Map" %}
-                  </a>
-                </div>
-                {% endif %}
-              <span>{{ object.latitude }}, {{ object.longitude }}</span>
-            {% else %}
-              {{ ''|placeholder }}
-            {% endif %}
-          </td>
-        </tr>
-      </table>
-    </div>
+    {{ site_panel }}
     {% include 'inc/panels/custom_fields.html' %}
     {% include 'inc/panels/custom_fields.html' %}
     {% include 'inc/panels/tags.html' %}
     {% include 'inc/panels/tags.html' %}
     {% include 'inc/panels/comments.html' %}
     {% include 'inc/panels/comments.html' %}
     {% plugin_left_page object %}
     {% plugin_left_page object %}
-    </div>
-    <div class="col col-12 col-md-6">
-      {% include 'inc/panels/related_objects.html' with filter_name='site_id' %}
-      {% include 'inc/panels/image_attachments.html' %}
-      {% plugin_right_page object %}
+  </div>
+  <div class="col col-12 col-md-6">
+    {% include 'inc/panels/related_objects.html' with filter_name='site_id' %}
+    {% include 'inc/panels/image_attachments.html' %}
+    {% plugin_right_page object %}
 	</div>
 	</div>
 </div>
 </div>
 <div class="row">
 <div class="row">