Merge pull request #24 from itsdave-de/feature/add-ip-addresses-usage-information-in-ip-network-view

Add IP addresses usage information for an IP network in IP network view
This commit is contained in:
itsdaveit 2022-08-26 11:59:24 +02:00 committed by GitHub
commit 097c9b9ef5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 247 additions and 3 deletions

View File

@ -14,5 +14,134 @@ frappe.ui.form.on('IP Network', {
}
})
})
getUsedIpsInNetwork(frm);
}
});
function getUsedIpsInNetwork(frm) {
displayLoader();
frm.call('get_used_ips', {})
.then((response) => {
const container = document.getElementById("usage-overview-table");
let tableBody = ``;
response?.message?.forEach((element) => {
tableBody += `
<tr>
<td
style="border: 1px solid #000; padding: 0.5rem 1rem; text-align: left; ${element?.ip_address_name ? 'cursor: pointer;' : ''}"
data-doctype-name="${element?.ip_address_name ?? ''}"
data-doctype-type="IP Address"
>
${(element?.ip_address === '') ? "-" : element?.ip_address}
</td>
<td
style="border: 1px solid #000; padding: 0.5rem 1rem; text-align: left; ${element?.ip_address_name ? 'cursor: pointer;' : ''}"
data-doctype-name="${element?.it_object_name ?? ''}"
data-doctype-type="IT Object"
>
${(element?.title === '') ? "-" : element?.title}
</td>
<td style="border: 1px solid #000; padding: 0.5rem 1rem; text-align: left;">${(element?.type === '') ? "-" : element?.type}</td>
</tr>
`;
});
const table = tableBody ? `
<table style="border-collapse: collapse; border: 2px solid #000; text-align: left; width: 100%; color: #000;">
<thead>
<tr>
<th scope="col" style="border: 1px solid #000; padding: 0.5rem 1rem;">IP</th>
<th scope="col" style="border: 1px solid #000; padding: 0.5rem 1rem;">Name</th>
<th scope="col" style="border: 1px solid #000; padding: 0.5rem 1rem;">Type</th>
</tr>
</thead>
<tbody>
${tableBody}
</tbody>
</table>
` : 'No IPs used for this network';
container.innerHTML = table;
document.querySelectorAll('[data-doctype-name]').forEach(element => {
element.addEventListener('click', (event) => {
event.preventDefault();
if (event.target.dataset?.doctypeName === '') {
return;
}
frappe.set_route('Form', event.target.dataset?.doctypeType, event.target.dataset?.doctypeName);
});
});
})
}
function displayLoader() {
const container = document.getElementById("usage-overview-table");
const loader = `
<div class="line-wobble"></div>
<style>
.line-wobble {
--uib-size: 80px;
--uib-speed: 1.75s;
--uib-color: black;
--uib-line-weight: 5px;
position: relative;
margin: 0 auto;
top: 45%;
display: flex;
align-items: center;
justify-content: center;
height: var(--uib-line-weight);
width: var(--uib-size);
border-radius: calc(var(--uib-line-weight) / 2);
overflow: hidden;
transform: translate3d(0, 0, 0);
}
.line-wobble::before {
content: '';
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 100%;
background-color: var(--uib-color);
opacity: 0.1;
}
.line-wobble::after {
content: '';
height: 100%;
width: 100%;
border-radius: calc(var(--uib-line-weight) / 2);
animation: wobble var(--uib-speed) ease-in-out infinite;
transform: translateX(-95%);
background-color: var(--uib-color);
}
@keyframes wobble {
0%,
100% {
transform: translateX(-95%);
}
50% {
transform: translateX(95%);
}
}
</style>
`;
// Set width and height to <div> parent element and to <form> grandparent element so relative width and height with % works greate
container.parentElement.parentElement.style.width = '100%';
container.parentElement.parentElement.style.height = '100%';
container.parentElement.style.width = '100%';
// Set this styles to showcase where the information will appear
container.style.width = '100%';
container.style.height = '100%';
container.innerHTML = loader;
}

View File

@ -27,7 +27,11 @@
"it_landscape",
"description",
"customer",
"location"
"location",
"ip_network_reserved_ranges_section",
"ip_network_reserved_ranges_table",
"usage_overview_section",
"usage_overview_table"
],
"fields": [
{
@ -146,10 +150,32 @@
"fieldname": "aditional_data_section",
"fieldtype": "Section Break",
"label": "Aditional Data"
},
{
"fieldname": "ip_network_reserved_ranges_section",
"fieldtype": "Section Break",
"label": "IP Network Reserved Ranges"
},
{
"fieldname": "ip_network_reserved_ranges_table",
"fieldtype": "Table",
"label": "IP Network Reserved Ranges Table",
"options": "IP Network Reserved Range"
},
{
"fieldname": "usage_overview_section",
"fieldtype": "Section Break",
"label": "Usage Overview "
},
{
"fieldname": "usage_overview_table",
"fieldtype": "HTML",
"label": "Usage Overview Table",
"options": "<div id=\"usage-overview-table\">Used IPs expected</div>"
}
],
"links": [],
"modified": "2022-06-17 11:20:37.093173",
"modified": "2022-08-18 10:28:34.233288",
"modified_by": "Administrator",
"module": "MSP",
"name": "IP Network",

View File

@ -8,7 +8,37 @@ from ipaddress import IPv4Address, IPv4Network
from frappe.model.document import Document
class IPNetwork(Document):
pass
@frappe.whitelist()
def get_used_ips(self):
values = {'ip_network': self.name, 'status': 'Decommissioned'}
result = []
result = frappe.db.sql("""
SELECT
ipa.name as ip_address_name,
ipa.ip_address,
ito.name as it_object_name,
ito.title,
ito.type
FROM `tabIP Address` ipa
JOIN `tabIT Object` ito
ON ipa.it_object = ito.name
WHERE ipa.ip_network = %(ip_network)s
AND ito.status != %(status)s
""", values=values, as_dict=1)
for ip_network_reserved_range in self.ip_network_reserved_ranges_table:
result.append({
'ip_address': ip_network_reserved_range.start,
'title': ip_network_reserved_range.type,
'type': 'DHCP Range Start'
})
result.append({
'ip_address': ip_network_reserved_range.end,
'title': ip_network_reserved_range.type,
'type': 'DHCP Range End'
})
return result
@frappe.whitelist()
def calculate_network_data(doc):

View File

@ -0,0 +1,51 @@
{
"actions": [],
"allow_rename": 1,
"creation": "2022-08-17 13:39:06.497802",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"start",
"end",
"type",
"description"
],
"fields": [
{
"fieldname": "start",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Start"
},
{
"fieldname": "end",
"fieldtype": "Data",
"in_list_view": 1,
"label": "End"
},
{
"fieldname": "type",
"fieldtype": "Select",
"in_list_view": 1,
"label": "Type",
"options": "DHCP range\nDHCP exclusion\nReservation"
},
{
"fieldname": "description",
"fieldtype": "Text Editor",
"label": "Description"
}
],
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
"modified": "2022-08-17 13:44:07.476976",
"modified_by": "Administrator",
"module": "MSP",
"name": "IP Network Reserved Range",
"owner": "Administrator",
"permissions": [],
"sort_field": "modified",
"sort_order": "DESC"
}

View File

@ -0,0 +1,8 @@
# Copyright (c) 2022, itsdave GmbH and contributors
# For license information, please see license.txt
# import frappe
from frappe.model.document import Document
class IPNetworkReservedRange(Document):
pass