Ready for netboxcommunity

This plugin has been re-developed for Netbox 4. The sync button has been redesigned as well as the colors of the sync table.
This commit is contained in:
NetTech2001
2024-05-17 16:00:56 -06:00
parent 51b75bc6d5
commit b48cfaca4b
15 changed files with 616 additions and 904 deletions

View File

@@ -1,65 +0,0 @@
{% if perms.dcim.change_device %}
<div class="dropdown">
<button id="device-type-sync" type="button" class="btn btn-primary dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">
Device type sync
</button>
<ul class="dropdown-menu" aria-labeled-by="device-type-sync">
{% if perms.dcim.add_consoleport %}
<li>
<a class="dropdown-item" href="{% url 'plugins:netbox_interface_sync:consoleport_comparison' device_id=device.id %}">
Console Ports
</a>
</li>
{% endif %}
{% if perms.dcim.add_consoleserverport %}
<li>
<a class="dropdown-item" href="{% url 'plugins:netbox_interface_sync:consoleserverport_comparison' device_id=device.id %}">
Console Server Ports
</a>
</li>
{% endif %}
{% if perms.dcim.add_powerport %}
<li>
<a class="dropdown-item" href="{% url 'plugins:netbox_interface_sync:powerport_comparison' device_id=device.id %}">
Power Ports
</a>
</li>
{% endif %}
{% if perms.dcim.add_poweroutlet %}
<li>
<a class="dropdown-item" href="{% url 'plugins:netbox_interface_sync:poweroutlet_comparison' device_id=device.id %}">
Power Outlets
</a>
</li>
{% endif %}
{% if perms.dcim.add_interface %}
<li>
<a class="dropdown-item" href="{% url 'plugins:netbox_interface_sync:interface_comparison' device_id=device.id %}">
Interfaces
</a>
</li>
{% endif %}
{# {% if perms.dcim.add_frontport %}#}
{# <li>#}
{# <a class="dropdown-item" href="{% url 'plugins:netbox_interface_sync:frontport_comparison' device_id=device.id %}">#}
{# Front Ports#}
{# </a>#}
{# </li>#}
{# {% endif %}#}
{% if perms.dcim.add_rearport %}
<li>
<a class="dropdown-item" href="{% url 'plugins:netbox_interface_sync:rearport_comparison' device_id=device.id %}">
Rear Ports
</a>
</li>
{% endif %}
{% if perms.dcim.add_devicebay %}
<li>
<a class="dropdown-item" href="{% url 'plugins:netbox_interface_sync:devicebay_comparison' device_id=device.id %}">
Device Bays
</a>
</li>
{% endif %}
</ul>
</div>
{% endif %}

View File

@@ -0,0 +1,3 @@
<a href="{% url 'plugins:netbox_interface_sync:interface_comparison' device_id=device.id %}" class="btn btn-purple"><i class="mdi mdi-sync" aria-hidden="true"></i>
Interface Sync
</a>

View File

@@ -0,0 +1,3 @@
<a href="{% url 'plugins:netbox_interface_sync:interface_comparison' device_id=device.id %}" class="btn btn-purple">
Interface Sync
</a>

View File

@@ -1,158 +0,0 @@
{% extends 'base/layout.html' %}
{% block title %}{{ device }} - {{ component_type_name|capfirst }} comparison{% endblock %}
{% block header %}
<nav class="breadcrumb-container px-3" aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="{% url 'dcim:device_list' %}">Devices</a></li>
<li class="breadcrumb-item"><a href="{% url 'dcim:device_list' %}?site={{ device.site.slug }}">{{ device.site }}</a></li>
<li class="breadcrumb-item"><a href="{% url 'dcim:device' pk=device.id %}">{{ device }}</a></li>
</ol>
</nav>
{{ block.super }}
{% endblock %}
{% block content %}
<style>
.caption-red {
caption-side: top;
color: red;
}
.caption-green {
caption-side: top;
color: green;
}
</style>
<script>
function toggle(event) {
event = event || window.event;
const src = event.target || event.srcElement || event;
const checkboxes = document.getElementsByName(src.id);
for(const checkbox of checkboxes) checkbox.checked = src.checked;
}
function uncheck(event) {
event = event || window.event;
const src = event.target || event.srcElement || event;
if (src.checked === false) {
document.getElementById(src.name).checked = false;
}
}
</script>
<form method="post">
{% csrf_token %}
<div class="table-responsive-xl">
<table class="table table-hover table-bordered">
{% if templates_count == components_count %}
<caption class="caption-green">
The device and device type have the same number of {{ component_type_name }}.
</caption>
{% else %}
<caption class="caption-red">
The device and device type have different number of {{ component_type_name }}.<br>
Device: {{ components_count }}<br>
Device type: {{ templates_count }}
</caption>
{% endif %}
<thead>
<tr>
<th scope="col" colspan="2">Device type</th>
<th scope="col">Actions</th>
<th scope="col" colspan="2">Device</th>
<th scope="col" colspan="2">Actions</th>
</tr>
<tr>
<th scope="col">Name</th>
<th scope="col">Attributes</th>
<th scope="col">
<label>
<input type="checkbox" id="add" onclick="toggle(this)">
Add to the device
</label>
</th>
<th scope="col">Name</th>
<th scope="col">Attributes</th>
<th scope="col">
<label>
<input type="checkbox" id="remove" onclick="toggle(this)">
Remove
</label>
</th>
<th scope="col">
<label>
<input type="checkbox" id="sync" onclick="toggle(this)">
Sync attributes
</label>
</th>
</tr>
</thead>
<tbody>
{% for component_template, component in comparison_items %}
<tr>
{% if component_template %}
<th scope="row" {% if not component %}class="table-danger"{% endif %}>
{% if component and component_template.name != component.name %}
<span style="background-color: #eab2b2">{{ component_template.name }}</span>
{% else %}
{{ component_template.name }}
{% endif %}
</th>
<td style="white-space:pre" {% if not component %}class="table-danger"{% endif %}>{{ component_template.fields_display }}</td>
<td {% if not component %}class="table-danger"{% endif %}>
{% if not component %}
<label>
<input type="checkbox" name="add" value="{{ component_template.id }}" onclick="uncheck(this)">
Add to device
</label>
{% endif %}
</td>
{% else %}
<th scope="row">&nbsp;</th>
<td>&nbsp;</td>
<td>&nbsp;</td>
{% endif %}
{% if component %}
<th scope="row" {% if not component_template %}class="table-success"{% endif %}>
{% if component_template and component_template.name != component.name %}
<span style="background-color: #cde8c2">{{ component.name }}</span>
{% else %}
{{ component.name }}
{% endif %}
</th>
<td style="white-space:pre" {% if not component_template %}class="table-success"{% endif %}>{{ component.fields_display }}</td>
<td {% if not component_template %}class="table-success"{% endif %}>
{% if not component_template %}
<label>
<input type="checkbox" name="remove" value="{{ component.id }}" onclick="uncheck(this)">
Remove
</label>
{% endif %}
</td>
<td {% if not component_template %}class="table-success"{% endif %}>
{% if component_template and component_template != component %}
<label>
<input type="checkbox" name="sync" value="{{ component.id }}" onclick="uncheck(this)">
Sync attributes
</label>
{% endif %}
</td>
{% else %}
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
{% endif %}
</tr>
{% endfor %}
</tbody>
</table>
</div>
<div>
<input type="submit" value="Apply" class="btn btn-primary" style="float: right;">
</div>
</form>
{% endblock %}

View File

@@ -0,0 +1,161 @@
{% extends 'base/layout.html' %}
{% block title %}{{ device }} - Interface comparison{% endblock %}
{% block header %}
<nav class="breadcrumb-container px-3" aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="{% url 'dcim:device_list' %}">Devices</a></li>
<li class="breadcrumb-item"><a href="{% url 'dcim:device_list' %}?site={{ device.site.slug }}">{{ device.site }}</a></li>
<li class="breadcrumb-item"><a href="{% url 'dcim:device' pk=device.id %}">{{ device }}</a></li>
</ol>
</nav>
{{ block.super }}
{% endblock %}
{% block content %}
<style>
.checkbox-group {
position: absolute;
}
</style>
<script>
function toggle(event) {
event = event || window.event;
var src = event.target || event.srcElement || event;
checkboxes = document.getElementsByName(src.id);
for(var checkbox of checkboxes) checkbox.checked = src.checked;
}
function uncheck(event) {
event = event || window.event;
var src = event.target || event.srcElement || event;
if (src.checked == false) {
document.getElementById(src.name).checked = false;
}
}
</script>
<p>
{% if templates_count == interfaces_count %}
The device and device type have the same number of interfaces.
{% else %}
The device and device type have a different number of interfaces.<br>
Device: {{ interfaces_count }}<br>
Device type: {{ templates_count }}
{% endif %}
</p>
<form method="post">
<!-- Interface templates -->
{% csrf_token %}
<table class="table" style="width: 50%; float: left;">
<tr>
<th colspan="2">Device Type</th>
<th>Actions</th>
</tr>
<tr>
<th>Name</th>
<th>Type</th>
<th>
<label class="checkbox-group">
<input type="checkbox" id="add_to_device" onclick="toggle(this)">
Add To The Device
</label>
</th>
</tr>
{% for template, interface in comparison_items %}
{% if template %}
<tr {% if not interface %}class="success" data-mark-connected="true"{% endif %}>
<td>
{% if interface and template.name != interface.name %}
<span style="background-color: #cde8c2">{{ template.name }}</span>
{% else %}
{{ template.name }}
{% endif %}
</td>
<td>{{ template.type_display }}</td>
<td>
{% if not interface %}
<label class="checkbox-group">
<input type="checkbox" name="add_to_device" value="{{ template.id }}" onclick="uncheck(this)">
Add To Device
</label>
{% endif %}
</td>
</tr>
{% else %}
<tr>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>
{% endif %}
{% endfor %}
</table>
<table class="table" style="width: 50%; float: right;">
<!-- Interfaces -->
<tr>
<th colspan="2">Device</th>
<th colspan="2">Actions</th>
</tr>
<tr>
<th>Name</th>
<th>Type</th>
<th>
<label class="checkbox-group">
<input type="checkbox" id="remove_from_device" onclick="toggle(this)">
Remove
</label>
</th>
<th>
<label class="checkbox-group">
<input type="checkbox" id="fix_name" onclick="toggle(this)">
Fix The Name
</label>
</th>
</tr>
{% for template, interface in comparison_items %}
{% if interface %}
<tr {% if not template %}class="danger" data-enabled="disabled"{% endif %}>
<td>
{% if template and template.name != interface.name %}
<span style="background-color: #eab2b2">{{ interface.name }}</span>
{% else %}
{{ interface.name }}
{% endif %}
</td>
<td>{{ interface.type_display }}</td>
<td>
{% if not template %}
<label class="checkbox-group">
<input type="checkbox" name="remove_from_device" value="{{ interface.id }}" onclick="uncheck(this)">
Remove
</label>
{% endif %}
</td>
<td>
{% if template and template.name != interface.name %}
<label class="checkbox-group">
<input type="checkbox" name="fix_name" value="{{ interface.id }}" onclick="uncheck(this)">
Fix Name
</label>
{% endif %}
</td>
</tr>
{% else %}
<tr>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>
{% endif %}
{% endfor %}
</table>
<div class="text-right">
<input type="submit" value="Apply" class="btn btn-primary">
</div>
</form>
{% endblock %}

View File

@@ -0,0 +1,161 @@
{% extends 'base/layout.html' %}
{% block title %}{{ device }} - Interface comparison{% endblock %}
{% block header %}
<nav class="breadcrumb-container px-3" aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="{% url 'dcim:device_list' %}">Devices</a></li>
<li class="breadcrumb-item"><a href="{% url 'dcim:device_list' %}?site={{ device.site.slug }}">{{ device.site }}</a></li>
<li class="breadcrumb-item"><a href="{% url 'dcim:device' pk=device.id %}">{{ device }}</a></li>
</ol>
</nav>
{{ block.super }}
{% endblock %}
{% block content %}
<style>
.checkbox-group {
position: absolute;
}
</style>
<script>
function toggle(event) {
event = event || window.event;
var src = event.target || event.srcElement || event;
checkboxes = document.getElementsByName(src.id);
for(var checkbox of checkboxes) checkbox.checked = src.checked;
}
function uncheck(event) {
event = event || window.event;
var src = event.target || event.srcElement || event;
if (src.checked == false) {
document.getElementById(src.name).checked = false;
}
}
</script>
<p>
{% if templates_count == interfaces_count %}
The device and device type have the same number of interfaces.
{% else %}
The device and device type have a different number of interfaces.<br>
Device: {{ interfaces_count }}<br>
Device type: {{ templates_count }}
{% endif %}
</p>
<form method="post">
<!-- Interface templates -->
{% csrf_token %}
<table class="table" style="width: 50%; float: left;">
<tr>
<th colspan="2">Device Type</th>
<th>Actions</th>
</tr>
<tr>
<th>Name</th>
<th>Type</th>
<th>
<label class="checkbox-group">
<input type="checkbox" id="add_to_device" onclick="toggle(this)">
Add To The Device
</label>
</th>
</tr>
{% for template, interface in comparison_items %}
{% if template %}
<tr {% if not interface %}class="success" data-enabled="enabled"{% endif %}>
<td>
{% if interface and template.name != interface.name %}
<span style="background-color: #cde8c2">{{ template.name }}</span>
{% else %}
{{ template.name }}
{% endif %}
</td>
<td>{{ template.type_display }}</td>
<td>
{% if not interface %}
<label class="checkbox-group">
<input type="checkbox" name="add_to_device" value="{{ template.id }}" onclick="uncheck(this)">
Add To Device
</label>
{% endif %}
</td>
</tr>
{% else %}
<tr>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>
{% endif %}
{% endfor %}
</table>
<table class="table" style="width: 50%; float: right;">
<!-- Interfaces -->
<tr>
<th colspan="2">Device</th>
<th colspan="2">Actions</th>
</tr>
<tr>
<th>Name</th>
<th>Type</th>
<th>
<label class="checkbox-group">
<input type="checkbox" id="remove_from_device" onclick="toggle(this)">
Remove
</label>
</th>
<th>
<label class="checkbox-group">
<input type="checkbox" id="fix_name" onclick="toggle(this)">
Fix The Name
</label>
</th>
</tr>
{% for template, interface in comparison_items %}
{% if interface %}
<tr {% if not template %}class="danger"{% endif %}>
<td>
{% if template and template.name != interface.name %}
<span style="background-color: #cde8c2">{{ interface.name }}</span>
{% else %}
{{ interface.name }}
{% endif %}
</td>
<td>{{ interface.type_display }}</td>
<td>
{% if not template %}
<label class="checkbox-group">
<input type="checkbox" name="remove_from_device" value="{{ interface.id }}" onclick="uncheck(this)">
Remove
</label>
{% endif %}
</td>
<td>
{% if template and template.name != interface.name %}
<label class="checkbox-group">
<input type="checkbox" name="fix_name" value="{{ interface.id }}" onclick="uncheck(this)">
Fix Name
</label>
{% endif %}
</td>
</tr>
{% else %}
<tr>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>
{% endif %}
{% endfor %}
</table>
<div class="text-right">
<input type="submit" value="Apply" class="btn btn-primary">
</div>
</form>
{% endblock %}

View File

@@ -0,0 +1,161 @@
{% extends 'base/layout.html' %}
{% block title %}{{ device }} - Interface comparison{% endblock %}
{% block header %}
<nav class="breadcrumb-container px-3" aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="{% url 'dcim:device_list' %}">Devices</a></li>
<li class="breadcrumb-item"><a href="{% url 'dcim:device_list' %}?site={{ device.site.slug }}">{{ device.site }}</a></li>
<li class="breadcrumb-item"><a href="{% url 'dcim:device' pk=device.id %}">{{ device }}</a></li>
</ol>
</nav>
{{ block.super }}
{% endblock %}
{% block content %}
<style>
.checkbox-group {
position: absolute;
}
</style>
<script>
function toggle(event) {
event = event || window.event;
var src = event.target || event.srcElement || event;
checkboxes = document.getElementsByName(src.id);
for(var checkbox of checkboxes) checkbox.checked = src.checked;
}
function uncheck(event) {
event = event || window.event;
var src = event.target || event.srcElement || event;
if (src.checked == false) {
document.getElementById(src.name).checked = false;
}
}
</script>
<p>
{% if templates_count == interfaces_count %}
The device and device type have the same number of interfaces.
{% else %}
The device and device type have a different number of interfaces.<br>
Device: {{ interfaces_count }}<br>
Device type: {{ templates_count }}
{% endif %}
</p>
<form method="post">
<!-- Interface templates -->
{% csrf_token %}
<table class="table" style="width: 50%; float: left;">
<tr>
<th colspan="2">Device Type</th>
<th>Actions</th>
</tr>
<tr>
<th>Name</th>
<th>Type</th>
<th>
<label class="checkbox-group">
<input type="checkbox" id="add_to_device" onclick="toggle(this)">
Add To The Device
</label>
</th>
</tr>
{% for template, interface in comparison_items %}
{% if template %}
<tr {% if not interface %}class="danger"{% endif %}>
<td>
{% if interface and template.name != interface.name %}
<span style="background-color: #eab2b2">{{ template.name }}</span>
{% else %}
{{ template.name }}
{% endif %}
</td>
<td>{{ template.type_display }}</td>
<td>
{% if not interface %}
<label class="checkbox-group">
<input type="checkbox" name="add_to_device" value="{{ template.id }}" onclick="uncheck(this)">
Add To Device
</label>
{% endif %}
</td>
</tr>
{% else %}
<tr>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>
{% endif %}
{% endfor %}
</table>
<table class="table" style="width: 50%; float: right;">
<!-- Interfaces -->
<tr>
<th colspan="2">Device</th>
<th colspan="2">Actions</th>
</tr>
<tr>
<th>Name</th>
<th>Type</th>
<th>
<label class="checkbox-group">
<input type="checkbox" id="remove_from_device" onclick="toggle(this)">
Remove
</label>
</th>
<th>
<label class="checkbox-group">
<input type="checkbox" id="fix_name" onclick="toggle(this)">
Fix The Name
</label>
</th>
</tr>
{% for template, interface in comparison_items %}
{% if interface %}
<tr {% if not template %}class="success"{% endif %}>
<td>
{% if template and template.name != interface.name %}
<span style="background-color: #cde8c2">{{ interface.name }}</span>
{% else %}
{{ interface.name }}
{% endif %}
</td>
<td>{{ interface.type_display }}</td>
<td>
{% if not template %}
<label class="checkbox-group">
<input type="checkbox" name="remove_from_device" value="{{ interface.id }}" onclick="uncheck(this)">
Remove
</label>
{% endif %}
</td>
<td>
{% if template and template.name != interface.name %}
<label class="checkbox-group">
<input type="checkbox" name="fix_name" value="{{ interface.id }}" onclick="uncheck(this)">
Fix Name
</label>
{% endif %}
</td>
</tr>
{% else %}
<tr>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>
{% endif %}
{% endfor %}
</table>
<div class="text-right">
<input type="submit" value="Apply" class="btn btn-primary">
</div>
</form>
{% endblock %}

View File

@@ -1,12 +1,10 @@
{% if config.include_interfaces_panel %}
<div class="card">
<h5 class="card-header">Number of interfaces</h5>
<div class="card-body">
Total interfaces: {{ interfaces|length }}<br>
{% if config.exclude_virtual_interfaces %}
Non-virtual interfaces: {{ real_interfaces|length }}<br>
{% endif %}
Interfaces in the assigned device type: {{ interface_templates|length }}
</div>
<div class="card">
<h5 class="card-header">Number of interfaces</h5>
<div class="card-body">
Total interfaces: {{ interfaces|length }}<br>
{% if config.exclude_virtual_interfaces %}
Non-virtual interfaces: {{ real_interfaces|length }}<br>
{% endif %}
Interfaces in the assigned device type: {{ interface_templates|length }}
</div>
{% endif %}
</div>