mirror of
https://github.com/netbox-community/netbox.git
synced 2024-05-10 07:54:54 +00:00
Clean up spacing for nav pills Markdown fields should default to using monospace font Wrap action buttons in object page header Fix page link style for non-HTMX paginators Clean up styling of Markdown preview widget Fix spacing around placeholder text for empty panel tables Remove obsolete templates Tweak checkbox input spacing Fix toggling of clear button for quick search Fix positioning of quick search filter dropdown Fix positioning of 'highlight device' button Fix styling for custom field group names Widen buttons on nav menu items Restyle the login page Fix active nav-pill background color in dark mode Fix spacing around 'map' button for sites
346 lines
18 KiB
HTML
346 lines
18 KiB
HTML
{% extends 'dcim/device/base.html' %}
|
|
{% load render_table from django_tables2 %}
|
|
{% load buttons %}
|
|
{% load static %}
|
|
{% load helpers %}
|
|
{% load plugins %}
|
|
{% load i18n %}
|
|
{% load mptt %}
|
|
|
|
{% block content %}
|
|
<div class="row">
|
|
<div class="col col-12 col-xl-6">
|
|
<div class="card">
|
|
<h5 class="card-header">{% trans "Device" %}</h5>
|
|
<table class="table table-hover attr-table">
|
|
<tr>
|
|
<th scope="row">{% trans "Region" %}</th>
|
|
<td>{% nested_tree object.site.region %}</td>
|
|
</tr>
|
|
<tr>
|
|
<th scope="row">{% trans "Site" %}</th>
|
|
<td>{{ object.site|linkify }}</td>
|
|
</tr>
|
|
<tr>
|
|
<th scope="row">{% trans "Location" %}</th>
|
|
<td>{% nested_tree object.location %}</td>
|
|
</tr>
|
|
<tr>
|
|
<th scope="row">{% trans "Rack" %}</th>
|
|
<td class="d-flex justify-content-between">
|
|
{% if object.rack %}
|
|
{{ object.rack|linkify }}
|
|
<a href="{{ object.rack.get_absolute_url }}?device={{ object.pk }}" class="btn btn-primary btn-sm d-print-none" title="{% trans "Highlight device in rack" %}">
|
|
<i class="mdi mdi-view-day-outline"></i>
|
|
</a>
|
|
{% else %}
|
|
{{ ''|placeholder }}
|
|
{% endif %}
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<th scope="row">{% trans "Position" %}</th>
|
|
<td>
|
|
{% if object.parent_bay %}
|
|
{% with object.parent_bay.device as parent %}
|
|
{{ parent|linkify }} / {{ object.parent_bay }}
|
|
{% if parent.position %}
|
|
(U{{ parent.position|floatformat }} / {{ parent.get_face_display }})
|
|
{% endif %}
|
|
{% endwith %}
|
|
{% elif object.rack and object.position %}
|
|
<span>U{{ object.position|floatformat }} / {{ object.get_face_display }}</span>
|
|
{% elif object.rack and object.device_type.u_height %}
|
|
<span class="badge text-bg-warning">{% trans "Not racked" %}</span>
|
|
{% else %}
|
|
{{ ''|placeholder }}
|
|
{% endif %}
|
|
</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 translate-middle-y d-print-none">
|
|
<a href="{{ config.MAPS_URL }}{{ object.latitude }},{{ object.longitude }}" target="_blank" class="btn btn-primary">
|
|
<i class="mdi mdi-map-marker"></i> {% trans "Map It" %}
|
|
</a>
|
|
</div>
|
|
{% endif %}
|
|
<span>{{ object.latitude }}, {{ object.longitude }}</span>
|
|
{% else %}
|
|
{{ ''|placeholder }}
|
|
{% endif %}
|
|
</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 "Device Type" %}</th>
|
|
<td>
|
|
{{ object.device_type|linkify:"get_full_name" }} ({{ object.device_type.u_height|floatformat }}U)
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<th scope="row">{% trans "Description" %}</th>
|
|
<td>{{ object.description|placeholder }}</td>
|
|
</tr>
|
|
<tr>
|
|
<th scope="row">{% trans "Airflow" %}</th>
|
|
<td>
|
|
{{ object.get_airflow_display|placeholder }}
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<th scope="row">{% trans "Serial Number" %}</th>
|
|
<td class="font-monospace">{{ object.serial|placeholder }}</td>
|
|
</tr>
|
|
<tr>
|
|
<th scope="row">{% trans "Asset Tag" %}</th>
|
|
<td class="font-monospace">{{ object.asset_tag|placeholder }}</td>
|
|
</tr>
|
|
<tr>
|
|
<th scope="row">{% trans "Config Template" %}</th>
|
|
<td>{{ object.config_template|linkify|placeholder }}</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
{% if vc_members %}
|
|
<div class="card">
|
|
<h5 class="card-header">{% trans "Virtual Chassis" %}</h5>
|
|
<table class="table table-hover attr-table">
|
|
<tr>
|
|
<th>{% trans "Device" %}</th>
|
|
<th>{% trans "Position" %}</th>
|
|
<th>{% trans "Master" %}</th>
|
|
<th>{% trans "Priority" %}</th>
|
|
</tr>
|
|
{% for vc_member in vc_members %}
|
|
<tr{% if vc_member == object %} class="info"{% endif %}>
|
|
<td>
|
|
{{ vc_member|linkify }}
|
|
</td>
|
|
<td>
|
|
{% badge vc_member.vc_position show_empty=True %}
|
|
</td>
|
|
<td>
|
|
{% if object.virtual_chassis.master == vc_member %}<i class="mdi mdi-check-bold"></i>{% endif %}
|
|
</td>
|
|
<td>
|
|
{{ vc_member.vc_priority|placeholder }}
|
|
</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</table>
|
|
<div class="card-footer text-end d-print-none">
|
|
<a href="{{ object.virtual_chassis.get_absolute_url }}" class="btn btn-primary">
|
|
<span class="mdi mdi-arrow-right-bold" aria-hidden="true"></span> {% trans "View Virtual Chassis" %}
|
|
</a>
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
{% include 'inc/panels/custom_fields.html' %}
|
|
{% include 'inc/panels/tags.html' %}
|
|
{% include 'inc/panels/comments.html' %}
|
|
<div class="card">
|
|
<h5 class="card-header">{% trans "Virtual Device Contexts" %}</h5>
|
|
{% htmx_table 'dcim:virtualdevicecontext_list' device_id=object.pk %}
|
|
{% if perms.dcim.add_virtualdevicecontext %}
|
|
<div class="card-footer text-end d-print-none">
|
|
<a href="{% url 'dcim:virtualdevicecontext_add' %}?device={{ object.pk }}" class="btn btn-primary">
|
|
<span class="mdi mdi-plus-thick" aria-hidden="true"></span> {% trans "Create VDC" %}
|
|
</a>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
{% plugin_left_page object %}
|
|
</div>
|
|
<div class="col col-12 col-xl-6">
|
|
<div class="card">
|
|
<h5 class="card-header">{% trans "Management" %}</h5>
|
|
<table class="table table-hover attr-table">
|
|
<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 "Role" %}</th>
|
|
<td>{{ object.role|linkify }}</td>
|
|
</tr>
|
|
<tr>
|
|
<th scope="row">{% trans "Platform" %}</th>
|
|
<td>{{ object.platform|linkify|placeholder }}</td>
|
|
</tr>
|
|
<tr>
|
|
<th scope="row">{% trans "Primary IPv4" %}</th>
|
|
<td>
|
|
{% if object.primary_ip4 %}
|
|
<a href="{{ object.primary_ip4.get_absolute_url }}" id="primary_ip4">{{ object.primary_ip4.address.ip }}</a>
|
|
{% if object.primary_ip4.nat_inside %}
|
|
({% trans "NAT for" %} <a href="{{ object.primary_ip4.nat_inside.get_absolute_url }}">{{ object.primary_ip4.nat_inside.address.ip }}</a>)
|
|
{% elif object.primary_ip4.nat_outside.exists %}
|
|
({% trans "NAT" %}: {% for nat in object.primary_ip4.nat_outside.all %}<a href="{{ nat.get_absolute_url }}">{{ nat.address.ip }}</a>{% if not forloop.last %}, {% endif %}{% endfor %})
|
|
{% endif %}
|
|
{% copy_content "primary_ip4" %}
|
|
{% else %}
|
|
{{ ''|placeholder }}
|
|
{% endif %}
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<th scope="row">{% trans "Primary IPv6" %}</th>
|
|
<td>
|
|
{% if object.primary_ip6 %}
|
|
<a href="{{ object.primary_ip6.get_absolute_url }}" id="primary_ip6">{{ object.primary_ip6.address.ip }}</a>
|
|
{% if object.primary_ip6.nat_inside %}
|
|
({% trans "NAT for" %} <a href="{{ object.primary_ip6.nat_inside.get_absolute_url }}">{{ object.primary_ip6.nat_inside.address.ip }}</a>)
|
|
{% elif object.primary_ip6.nat_outside.exists %}
|
|
({% trans "NAT" %}: {% for nat in object.primary_ip6.nat_outside.all %}<a href="{{ nat.get_absolute_url }}">{{ nat.address.ip }}</a>{% if not forloop.last %}, {% endif %}{% endfor %})
|
|
{% endif %}
|
|
{% copy_content "primary_ip6" %}
|
|
{% else %}
|
|
{{ ''|placeholder }}
|
|
{% endif %}
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<th scope="row">Out-of-band IP</th>
|
|
<td>
|
|
{% if object.oob_ip %}
|
|
<a href="{{ object.oob_ip.get_absolute_url }}" id="oob_ip">{{ object.oob_ip.address.ip }}</a>
|
|
{% copy_content "oob_ip" %}
|
|
{% else %}
|
|
{{ ''|placeholder }}
|
|
{% endif %}
|
|
</td>
|
|
</tr>
|
|
{% if object.cluster %}
|
|
<tr>
|
|
<th>{% trans "Cluster" %}</th>
|
|
<td>
|
|
{% if object.cluster.group %}
|
|
{{ object.cluster.group|linkify }} /
|
|
{% endif %}
|
|
{{ object.cluster|linkify }}
|
|
</td>
|
|
</tr>
|
|
{% endif %}
|
|
</table>
|
|
</div>
|
|
{% if object.powerports.exists and object.poweroutlets.exists %}
|
|
<div class="card">
|
|
<h5 class="card-header">{% trans "Power Utilization" %}</h5>
|
|
<table class="table table-hover">
|
|
<thead>
|
|
<tr>
|
|
<th>{% trans "Input" %}</th>
|
|
<th>{% trans "Outlets" %}</th>
|
|
<th>{% trans "Allocated" %}</th>
|
|
<th>{% trans "Available" %}</th>
|
|
<th>{% trans "Utilization" %}</th>
|
|
</tr>
|
|
</thead>
|
|
{% for powerport in object.powerports.all %}
|
|
{% with utilization=powerport.get_power_draw powerfeed=powerport.connected_endpoints.0 %}
|
|
<tr>
|
|
<td>{{ powerport }}</td>
|
|
<td>{{ utilization.outlet_count }}</td>
|
|
<td>{{ utilization.allocated }}{% trans "VA" %}</td>
|
|
{% if powerfeed.available_power %}
|
|
<td>{{ powerfeed.available_power }}{% trans "VA" %}</td>
|
|
<td>{% utilization_graph utilization.allocated|percentage:powerfeed.available_power %}</td>
|
|
{% else %}
|
|
<td class="text-muted">—</td>
|
|
<td class="text-muted">—</td>
|
|
{% endif %}
|
|
</tr>
|
|
{% for leg in utilization.legs %}
|
|
<tr>
|
|
<td style="padding-left: 20px">
|
|
{% trans "Leg" context "Leg of a power feed" %} {{ leg.name }}
|
|
</td>
|
|
<td>{{ leg.outlet_count }}</td>
|
|
<td>{{ leg.allocated }}</td>
|
|
{% if powerfeed.available_power %}
|
|
{% with phase_available=powerfeed.available_power|divide:3 %}
|
|
<td>{{ phase_available }}{% trans "VA" %}</td>
|
|
<td>{% utilization_graph leg.allocated|percentage:phase_available %}</td>
|
|
{% endwith %}
|
|
{% else %}
|
|
<td class="text-muted">—</td>
|
|
<td class="text-muted">—</td>
|
|
{% endif %}
|
|
</tr>
|
|
{% endfor %}
|
|
{% endwith %}
|
|
{% endfor %}
|
|
</table>
|
|
</div>
|
|
{% endif %}
|
|
<div class="card">
|
|
<h5 class="card-header">{% trans "Services" %}</h5>
|
|
{% htmx_table 'ipam:service_list' device_id=object.pk %}
|
|
{% if perms.ipam.add_service %}
|
|
<div class="card-footer text-end d-print-none">
|
|
<a href="{% url 'ipam:service_add' %}?device={{ object.pk }}" class="btn btn-primary">
|
|
<span class="mdi mdi-plus-thick" aria-hidden="true"></span> {% trans "Add a service" %}
|
|
</a>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
{% include 'inc/panels/image_attachments.html' %}
|
|
<div class="card">
|
|
<h5 class="card-header">{% trans "Dimensions" %}</h5>
|
|
<table class="table table-hover attr-table">
|
|
<tr>
|
|
<th scope="row">{% trans "Height" %}</th>
|
|
<td>
|
|
{{ object.device_type.u_height }}U
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<th scope="row">{% trans "Weight" %}</th>
|
|
<td>
|
|
{% if object.total_weight %}
|
|
{{ object.total_weight|floatformat }} {% trans "Kilograms" %}
|
|
{% else %}
|
|
{{ ''|placeholder }}
|
|
{% endif %}
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
{% if object.rack and object.position %}
|
|
<div class="row" style="margin-bottom: 20px">
|
|
<div class="col col-md-6 col-sm-6 col-xs-12 text-center">
|
|
<div style="margin-left: 30px">
|
|
<h4>{% trans "Front" %}</h4>
|
|
{% include 'dcim/inc/rack_elevation.html' with object=object.rack face='front' extra_params=svg_extra %}
|
|
</div>
|
|
</div>
|
|
<div class="col col-md-6 col-sm-6 col-xs-12 text-center">
|
|
<div style="margin-left: 30px">
|
|
<h4>{% trans "Rear" %}</h4>
|
|
{% include 'dcim/inc/rack_elevation.html' with object=object.rack face='rear' extra_params=svg_extra %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
{% plugin_right_page object %}
|
|
</div>
|
|
</div>
|
|
<div class="row">
|
|
<div class="col col-md-12">
|
|
{% plugin_full_width_page object %}
|
|
</div>
|
|
</div>
|
|
{% endblock %}
|