mirror of
				https://github.com/itsdave-de/msp.git
				synced 2025-10-30 17:07:09 -03:00 
			
		
		
		
	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:
		
						commit
						097c9b9ef5
					
				| @ -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; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | |||||||
| @ -27,7 +27,11 @@ | |||||||
|   "it_landscape", |   "it_landscape", | ||||||
|   "description", |   "description", | ||||||
|   "customer", |   "customer", | ||||||
|   "location" |   "location", | ||||||
|  |   "ip_network_reserved_ranges_section", | ||||||
|  |   "ip_network_reserved_ranges_table", | ||||||
|  |   "usage_overview_section", | ||||||
|  |   "usage_overview_table" | ||||||
|  ], |  ], | ||||||
|  "fields": [ |  "fields": [ | ||||||
|   { |   { | ||||||
| @ -146,10 +150,32 @@ | |||||||
|    "fieldname": "aditional_data_section", |    "fieldname": "aditional_data_section", | ||||||
|    "fieldtype": "Section Break", |    "fieldtype": "Section Break", | ||||||
|    "label": "Aditional Data" |    "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": [], |  "links": [], | ||||||
|  "modified": "2022-06-17 11:20:37.093173", |  "modified": "2022-08-18 10:28:34.233288", | ||||||
|  "modified_by": "Administrator", |  "modified_by": "Administrator", | ||||||
|  "module": "MSP", |  "module": "MSP", | ||||||
|  "name": "IP Network", |  "name": "IP Network", | ||||||
|  | |||||||
| @ -8,7 +8,37 @@ from ipaddress import IPv4Address, IPv4Network | |||||||
| from frappe.model.document import Document | from frappe.model.document import Document | ||||||
| 
 | 
 | ||||||
| class IPNetwork(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() | @frappe.whitelist() | ||||||
| def calculate_network_data(doc): | def calculate_network_data(doc): | ||||||
|  | |||||||
| @ -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" | ||||||
|  | } | ||||||
| @ -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 | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user