1
0
mirror of https://github.com/netbox-community/netbox.git synced 2024-05-10 07:54:54 +00:00

Merge branch 'develop' into feature

This commit is contained in:
jeremystretch
2022-11-16 11:42:32 -05:00
28 changed files with 307 additions and 206 deletions

View File

@ -26,78 +26,15 @@
{# Page title #}
<title>{% block title %}Home{% endblock %} | NetBox</title>
<script
type="text/javascript"
src="{% static 'setmode.js' %}"
onerror="window.location='{% url 'media_failure' %}?filename=setmode.js'">
</script>
<script type="text/javascript">
/**
* Set the color mode on the `<html/>` element and in local storage.
*
* @param mode {"dark" | "light"} NetBox Color Mode.
* @param inferred {boolean} Value is inferred from browser/system preference.
*/
function setMode(mode, inferred) {
document.documentElement.setAttribute("data-netbox-color-mode", mode);
localStorage.setItem("netbox-color-mode", mode);
localStorage.setItem("netbox-color-mode-inferred", inferred);
}
/**
* Determine the best initial color mode to use prior to rendering.
*/
(function () {
try {
// Browser prefers dark color scheme.
var preferDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
// Browser prefers light color scheme.
var preferLight = window.matchMedia("(prefers-color-scheme: light)").matches;
// Client NetBox color-mode override.
var clientMode = localStorage.getItem("netbox-color-mode");
// NetBox server-rendered value.
var serverMode = document.documentElement.getAttribute("data-netbox-color-mode");
// Color mode is inferred from browser/system preference and not deterministically set by
// the client or server.
var inferred = JSON.parse(localStorage.getItem("netbox-color-mode-inferred"));
if (inferred === true && (serverMode === "light" || serverMode === "dark")) {
// The color mode was previously inferred from browser/system preference, but
// the server now has a value, so we should use the server's value.
return setMode(serverMode, false);
}
if (clientMode === null && (serverMode === "light" || serverMode === "dark")) {
// If the client mode is not set but the server mode is, use the server mode.
return setMode(serverMode, false);
}
if (clientMode !== null && serverMode === "unset") {
// The color mode has been set, deterministically or otherwise, and the server
// has no preference or has not been set. Use the client mode, but allow it to
/// be overridden by the server if/when a server value exists.
return setMode(clientMode, true);
}
if (
clientMode !== null &&
(serverMode === "light" || serverMode === "dark") &&
clientMode !== serverMode
) {
// If the client mode is set and is different than the server mode (which is also set),
// use the client mode over the server mode, as it should be more recent.
return setMode(clientMode, false);
}
if (clientMode === serverMode) {
// If the client and server modes match, use that value.
return setMode(clientMode, false);
}
if (preferDark && serverMode === "unset") {
// If the server mode is not set but the browser prefers dark mode, use dark mode, but
// allow it to be overridden by an explicit preference.
return setMode("dark", true);
}
if (preferLight && serverMode === "unset") {
// If the server mode is not set but the browser prefers light mode, use light mode,
// but allow it to be overridden by an explicit preference.
return setMode("light", true);
}
} catch (error) {
// In the event of an error, log it to the console and set the mode to light mode.
console.error(error);
}
return setMode("light", true);
initMode()
})();
window.CSRF_TOKEN = "{{ csrf_token }}";
</script>

View File

@ -64,19 +64,19 @@
<h5 class="card-header">Environment</h5>
<div class="card-body">
<table class="table">
<tr id="status-cpu" class="bg-light">
<tr id="status-cpu">
<th colspan="2"><i class="mdi mdi-gauge"></i> CPU</th>
</tr>
<tr id="status-memory" class="bg-light">
<tr id="status-memory">
<th colspan="2"><i class="mdi mdi-chip"></i> Memory</th>
</tr>
<tr id="status-temperature" class="bg-light">
<tr id="status-temperature">
<th colspan="2"><i class="mdi mdi-thermometer"></i> Temperature</th>
</tr>
<tr id="status-fans" class="bg-light">
<tr id="status-fans">
<th colspan="2"><i class="mdi mdi-fan"></i> Fans</th>
</tr>
<tr id="status-power" class="bg-light">
<tr id="status-power">
<th colspan="2"><i class="mdi mdi-power"></i> Power</th>
</tr>
<tr class="napalm-table-placeholder d-none invisible">

View File

@ -7,6 +7,10 @@
<td>Site</td>
<td>{{ terminations.0.device.site|linkify }}</td>
</tr>
<tr>
<td>Location</td>
<td>{{ terminations.0.device.location|linkify|placeholder }}</td>
</tr>
<tr>
<td>Rack</td>
<td>{{ terminations.0.device.rack|linkify|placeholder }}</td>

View File

@ -4,10 +4,24 @@
{% load render_table from django_tables2 %}
{% block extra_controls %}
{% if perms.dcim.add_devicetype %}
<a href="{% url 'dcim:devicetype_add' %}?manufacturer={{ object.pk }}" class="btn btn-sm btn-primary">
<span class="mdi mdi-plus-thick" aria-hidden="true"></span> Add Device Type
</a>
{% if perms.dcim.add_devicetype or perms.dcim.add_moduletype %}
<div class="dropdown">
<button id="add-components" type="button" class="btn btn-sm btn-primary dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">
<i class="mdi mdi-plus-thick" aria-hidden="true"></i> Add
</button>
<ul class="dropdown-menu" aria-labeled-by="add-components">
{% if perms.dcim.add_devicetype %}
<li><a class="dropdown-item" href="{% url 'dcim:devicetype_add' %}?manufacturer={{ object.pk }}">
Add Device Type
</a></li>
{% endif %}
{% if perms.dcim.add_moduletype %}
<li><a class="dropdown-item" href="{% url 'dcim:moduletype_add' %}?manufacturer={{ object.pk }}">
Add Module Type
</a></li>
{% endif %}
</ul>
</div>
{% endif %}
{% endblock extra_controls %}

View File

@ -77,10 +77,10 @@
</button>
<ul class="dropdown-menu dropdown-menu-end">
<li>
<a href="{% url 'dcim:cable_add' %}?a_terminations_type=dcim.powerportport&a_terminations={{ object.pk }}&termination_b_type=dcim.poweroutlet&termination_b_site={{ object.device.site.pk }}&termination_b_rack={{ object.device.rack.pk }}&return_url={{ object.get_absolute_url }}" class="dropdown-item">Power Outlet</a>
<a href="{% url 'dcim:cable_add' %}?a_terminations_type=dcim.powerport&a_terminations={{ object.pk }}&b_terminations_type=dcim.poweroutlet&termination_b_site={{ object.device.site.pk }}&termination_b_rack={{ object.device.rack.pk }}&return_url={{ object.get_absolute_url }}" class="dropdown-item">Power Outlet</a>
</li>
<li>
<a href="{% url 'dcim:cable_add' %}?a_terminations_type=dcim.powerportport&a_terminations={{ object.pk }}&termination_b_type=dcim.powerfeed&termination_b_site={{ object.device.site.pk }}&termination_b_rack={{ object.device.rack.pk }}&return_url={{ object.get_absolute_url }}" class="dropdown-item">Power Feed</a>
<a href="{% url 'dcim:cable_add' %}?a_terminations_type=dcim.powerport&a_terminations={{ object.pk }}&b_terminations_type=dcim.powerfeed&termination_b_site={{ object.device.site.pk }}&termination_b_rack={{ object.device.rack.pk }}&return_url={{ object.get_absolute_url }}" class="dropdown-item">Power Feed</a>
</li>
</ul>
</span>

View File

@ -70,64 +70,65 @@ Context:
{% applied_filters model filter_form request.GET %}
{% endif %}
{# "Select all" form #}
{% if table.paginator.num_pages > 1 %}
<div id="select-all-box" class="d-none card noprint">
<form method="post" class="form col-md-12">
{% csrf_token %}
<div class="card-body">
<div class="float-end">
<form method="post" class="form form-horizontal">
{% csrf_token %}
{# "Select all" form #}
{% if table.paginator.num_pages > 1 %}
<div id="select-all-box" class="d-none card noprint">
<div class="form col-md-12">
<div class="card-body">
<div class="float-end">
{% if 'bulk_edit' in actions %}
{% bulk_edit_button model query_params=request.GET %}
{% endif %}
{% if 'bulk_delete' in actions %}
{% bulk_delete_button model query_params=request.GET %}
{% endif %}
</div>
<div class="form-check">
<input type="checkbox" id="select-all" name="_all" class="form-check-input" />
<label for="select-all" class="form-check-label">
Select <strong>all {{ table.rows|length }} {{ table.data.verbose_name_plural }}</strong> matching query
</label>
</div>
</div>
</div>
</div>
{% endif %}
{# Object table controls #}
{% include 'inc/table_controls_htmx.html' with table_modal="ObjectTable_config" %}
<div class="form form-horizontal">
{% csrf_token %}
<input type="hidden" name="return_url" value="{% if return_url %}{{ return_url }}{% else %}{{ request.path }}{% if request.GET %}?{{ request.GET.urlencode }}{% endif %}{% endif %}" />
{# Object table #}
{% if prerequisite_model %}
{% include 'inc/missing_prerequisites.html' %}
{% endif %}
<div class="card">
<div class="card-body" id="object_list">
{% include 'htmx/table.html' %}
</div>
</div>
{# Form buttons #}
<div class="noprint bulk-buttons">
<div class="bulk-button-group">
{% block bulk_buttons %}
{% if 'bulk_edit' in actions %}
{% bulk_edit_button model query_params=request.GET %}
{% endif %}
{% if 'bulk_delete' in actions %}
{% bulk_delete_button model query_params=request.GET %}
{% endif %}
</div>
<div class="form-check">
<input type="checkbox" id="select-all" name="_all" class="form-check-input" />
<label for="select-all" class="form-check-label">
Select <strong>all {{ table.rows|length }} {{ table.data.verbose_name_plural }}</strong> matching query
</label>
</div>
{% endblock %}
</div>
</form>
</div>
{% endif %}
{# Object table controls #}
{% include 'inc/table_controls_htmx.html' with table_modal="ObjectTable_config" %}
<form method="post" class="form form-horizontal">
{% csrf_token %}
<input type="hidden" name="return_url" value="{% if return_url %}{{ return_url }}{% else %}{{ request.path }}{% if request.GET %}?{{ request.GET.urlencode }}{% endif %}{% endif %}" />
{# Object table #}
{% if prerequisite_model %}
{% include 'inc/missing_prerequisites.html' %}
{% endif %}
<div class="card">
<div class="card-body" id="object_list">
{% include 'htmx/table.html' %}
</div>
</div>
{# Form buttons #}
<div class="noprint bulk-buttons">
<div class="bulk-button-group">
{% block bulk_buttons %}
{% if 'bulk_edit' in actions %}
{% bulk_edit_button model query_params=request.GET %}
{% endif %}
{% if 'bulk_delete' in actions %}
{% bulk_delete_button model query_params=request.GET %}
{% endif %}
{% endblock %}
</div>
</div>
</form>
</div>

View File

@ -25,7 +25,7 @@
<tr>
<th scope="row">Assignments</th>
<td>
<a href="{% url 'tenancy:contact_list' %}?role={{ object.slug }}">{{ assignment_count }}</a>
{{ assignment_count }}
</td>
</tr>
</table>

View File

@ -97,6 +97,12 @@
<h2><a href="{% url 'ipam:vlan_list' %}?tenant_id={{ object.pk }}" class="stat-btn btn {% if stats.vlan_count %}btn-primary{% else %}btn-outline-dark{% endif %} btn-lg">{{ stats.vlan_count }}</a></h2>
<p>VLANs</p>
</div>
<div class="col col-md-4 text-center">
<h2><a href="{% url 'ipam:l2vpn_list' %}?tenant_id={{ object.pk }}" class="stat-btn btn {% if stats.l2vpn_count %}btn-primary{% else %}btn-outline-dark{% endif %} btn-lg">{{ stats.l2vpn_count }}</a></h2>
<p>L2VPNs</p>
</div>
<div class="col col-md-4 text-center">
<h2><a href="{% url 'circuits:circuit_list' %}?tenant_id={{ object.pk }}" class="stat-btn btn {% if stats.circuit_count %}btn-primary{% else %}btn-outline-dark{% endif %} btn-lg">{{ stats.circuit_count }}</a></h2>
<p>Circuits</p>