Spaces:
Running
Running
| document.addEventListener('DOMContentLoaded', function() { | |
| const internetBtn = document.getElementById('internetBtn'); | |
| const l2lBtn = document.getElementById('l2lBtn'); | |
| const internetForm = document.getElementById('internetForm'); | |
| const l2lForm = document.getElementById('l2lForm'); | |
| const calculateBtn = document.getElementById('calculateBtn'); | |
| const ipRangeInput = document.getElementById('ipRange'); | |
| const ipTableBody = document.getElementById('ipTableBody'); | |
| const ipTableContainer = document.getElementById('ipTableContainer'); | |
| const generateBtn = document.getElementById('generateBtn'); | |
| const outputContainer = document.getElementById('outputContainer'); | |
| const emailOutput = document.getElementById('emailOutput'); | |
| const copyBtn = document.getElementById('copyBtn'); | |
| // Toggle between service types | |
| internetBtn.addEventListener('click', function() { | |
| internetBtn.classList.add('bg-blue-600', 'text-white'); | |
| internetBtn.classList.remove('bg-gray-200', 'text-gray-800'); | |
| l2lBtn.classList.remove('bg-blue-600', 'text-white'); | |
| l2lBtn.classList.add('bg-gray-200', 'text-gray-800'); | |
| internetForm.classList.remove('hidden'); | |
| l2lForm.classList.add('hidden'); | |
| outputContainer.classList.add('hidden'); | |
| }); | |
| // Initialize Feather Icons | |
| feather.replace(); | |
| l2lBtn.addEventListener('click', function() { | |
| l2lBtn.classList.add('bg-blue-600', 'text-white'); | |
| l2lBtn.classList.remove('bg-gray-200', 'text-gray-800'); | |
| internetBtn.classList.remove('bg-blue-600', 'text-white'); | |
| internetBtn.classList.add('bg-gray-200', 'text-gray-800'); | |
| l2lForm.classList.remove('hidden'); | |
| internetForm.classList.add('hidden'); | |
| outputContainer.classList.add('hidden'); | |
| }); | |
| // Calculate IP addresses | |
| calculateBtn.addEventListener('click', function() { | |
| const ipRange = ipRangeInput.value.trim(); | |
| if (!ipRange) { | |
| alert('Please enter a valid IP range (e.g., 190.220.1.216/29)'); | |
| return; | |
| } | |
| try { | |
| const [baseIp, cidr] = ipRange.split('/'); | |
| const cidrNumber = parseInt(cidr); | |
| if (cidrNumber < 0 || cidrNumber > 32) { | |
| throw new Error('Invalid CIDR'); | |
| } | |
| const subnetMask = calculateSubnetMask(cidrNumber); | |
| const ipParts = baseIp.split('.').map(Number); | |
| const networkAddress = calculateNetworkAddress(ipParts, cidrNumber); | |
| const broadcastAddress = calculateBroadcastAddress(networkAddress, cidrNumber); | |
| // Clear previous results | |
| ipTableBody.innerHTML = ''; | |
| // Add network address row | |
| addTableRow('RED LAN', formatIp(networkAddress), subnetMask); | |
| // Calculate usable IPs (network +1 to broadcast -1) | |
| const startIp = [...networkAddress]; | |
| incrementIp(startIp); | |
| // Calculate the number of usable hosts | |
| const usableHosts = Math.pow(2, 32 - cidrNumber) - 2; | |
| // Add gateway (first usable IP) | |
| addTableRow('GATEWAY', formatIp(startIp), subnetMask); | |
| // Increment for next IP | |
| incrementIp(startIp); | |
| // Add available client IPs | |
| for (let i = 0; i < usableHosts - 1; i++) { | |
| if (formatIp(startIp) === formatIp(broadcastAddress)) break; | |
| addTableRow('DISPONIBLE CLIENTE', formatIp(startIp), subnetMask); | |
| incrementIp(startIp); | |
| } | |
| // Add broadcast address | |
| addTableRow('BROADCAST', formatIp(broadcastAddress), subnetMask); | |
| ipTableContainer.classList.remove('hidden'); | |
| } catch (error) { | |
| alert('Invalid IP range format. Please use format like 190.220.1.216/29'); | |
| console.error(error); | |
| } | |
| }); | |
| // Generate email template | |
| generateBtn.addEventListener('click', function() { | |
| if (internetBtn.classList.contains('bg-blue-600')) { | |
| generateInternetEmail(); | |
| } else { | |
| generateL2LEmail(); | |
| } | |
| outputContainer.classList.remove('hidden'); | |
| }); | |
| // Copy table to clipboard | |
| const copyTableBtn = document.getElementById('copyTableBtn'); | |
| copyTableBtn.addEventListener('click', function() { | |
| let tableText = 'Type\tIP Address\tSubnet Mask\n'; | |
| const rows = ipTableBody.querySelectorAll('tr'); | |
| rows.forEach(row => { | |
| const cells = row.querySelectorAll('td'); | |
| tableText += `${cells[0].textContent}\t${cells[1].textContent}\t${cells[2].textContent}\n`; | |
| }); | |
| navigator.clipboard.writeText(tableText).then(() => { | |
| const originalText = copyTableBtn.innerHTML; | |
| copyTableBtn.innerHTML = '<i data-feather="check" class="mr-2"></i> Copied!'; | |
| setTimeout(() => { | |
| copyTableBtn.innerHTML = originalText; | |
| feather.replace(); | |
| }, 2000); | |
| }); | |
| }); | |
| // Make sure calculate button works immediately | |
| calculateBtn.addEventListener('click', calculateIPs); | |
| function calculateIPs() { | |
| const ipRange = ipRangeInput.value.trim(); | |
| if (!ipRange) { | |
| alert('Please enter a valid IP range (e.g., 190.220.1.216/29)'); | |
| return; | |
| } | |
| try { | |
| const [baseIp, cidr] = ipRange.split('/'); | |
| const cidrNumber = parseInt(cidr); | |
| if (cidrNumber < 0 || cidrNumber > 32) { | |
| throw new Error('Invalid CIDR'); | |
| } | |
| const subnetMask = calculateSubnetMask(cidrNumber); | |
| const ipParts = baseIp.split('.').map(Number); | |
| const networkAddress = calculateNetworkAddress(ipParts, cidrNumber); | |
| const broadcastAddress = calculateBroadcastAddress(networkAddress, cidrNumber); | |
| // Clear previous results | |
| ipTableBody.innerHTML = ''; | |
| // Add network address row | |
| addTableRow('RED LAN', formatIp(networkAddress), subnetMask); | |
| // Calculate usable IPs (network +1 to broadcast -1) | |
| const startIp = [...networkAddress]; | |
| incrementIp(startIp); | |
| // Calculate the number of usable hosts | |
| const usableHosts = Math.pow(2, 32 - cidrNumber) - 2; | |
| // Add gateway (first usable IP) | |
| addTableRow('GATEWAY', formatIp(startIp), subnetMask); | |
| // Increment for next IP | |
| incrementIp(startIp); | |
| // Add available client IPs | |
| for (let i = 0; i < usableHosts - 1; i++) { | |
| if (formatIp(startIp) === formatIp(broadcastAddress)) break; | |
| addTableRow('DISPONIBLE CLIENTE', formatIp(startIp), subnetMask); | |
| incrementIp(startIp); | |
| } | |
| // Add broadcast address | |
| addTableRow('BROADCAST', formatIp(broadcastAddress), subnetMask); | |
| ipTableContainer.classList.remove('hidden'); | |
| } catch (error) { | |
| alert('Invalid IP range format. Please use format like 190.220.1.216/29'); | |
| console.error(error); | |
| } | |
| } | |
| // Copy email to clipboard | |
| copyBtn.addEventListener('click', function() { | |
| const textToCopy = emailOutput.textContent; | |
| navigator.clipboard.writeText(textToCopy).then(() => { | |
| const originalText = copyBtn.innerHTML; | |
| copyBtn.innerHTML = '<i data-feather="check" class="mr-2"></i> Copied!'; | |
| feather.replace(); | |
| setTimeout(() => { | |
| copyBtn.innerHTML = originalText; | |
| feather.replace(); | |
| }, 2000); | |
| }).catch(err => { | |
| console.error('Failed to copy text: ', err); | |
| copyBtn.innerHTML = '<i data-feather="x" class="mr-2"></i> Failed!'; | |
| feather.replace(); | |
| setTimeout(() => { | |
| copyBtn.innerHTML = originalText; | |
| feather.replace(); | |
| }, 2000); | |
| }); | |
| }); | |
| // Helper functions | |
| function addTableRow(type, ip, mask) { | |
| if (!ipTableBody) return; | |
| const row = document.createElement('tr'); | |
| row.innerHTML = ` | |
| <td class="font-medium">${type}</td> | |
| <td class="font-mono">${ip}</td> | |
| <td class="font-mono">${mask}</td> | |
| `; | |
| ipTableBody.appendChild(row); | |
| } | |
| function calculateSubnetMask(cidr) { | |
| let mask = []; | |
| for (let i = 0; i < 4; i++) { | |
| const bits = Math.min(8, Math.max(0, cidr - i * 8)); | |
| mask.push(256 - Math.pow(2, 8 - bits)); | |
| } | |
| return mask.join('.'); | |
| } | |
| function calculateNetworkAddress(ip, cidr) { | |
| const network = [...ip]; | |
| for (let i = 0; i < 4; i++) { | |
| const bits = Math.min(8, Math.max(0, cidr - i * 8)); | |
| if (bits === 0) { | |
| network[i] = 0; | |
| } else if (bits < 8) { | |
| network[i] = network[i] & (256 - Math.pow(2, 8 - bits)); | |
| } | |
| } | |
| return network; | |
| } | |
| function calculateBroadcastAddress(network, cidr) { | |
| const broadcast = [...network]; | |
| for (let i = 0; i < 4; i++) { | |
| const bits = Math.min(8, Math.max(0, cidr - i * 8)); | |
| if (bits < 8) { | |
| broadcast[i] = broadcast[i] | (Math.pow(2, 8 - bits) - 1); | |
| } | |
| } | |
| return broadcast; | |
| } | |
| function incrementIp(ip) { | |
| for (let i = 3; i >= 0; i--) { | |
| if (ip[i] < 255) { | |
| ip[i]++; | |
| break; | |
| } else { | |
| ip[i] = 0; | |
| } | |
| } | |
| } | |
| function formatIp(ipArray) { | |
| return ipArray.join('.'); | |
| } | |
| function generateInternetEmail() { | |
| const client = document.getElementById('client').value; | |
| const serviceNumber = document.getElementById('serviceNumber').value; | |
| const address = document.getElementById('address').value; | |
| const bandwidth = document.getElementById('bandwidth').value; | |
| const ipRange = document.getElementById('ipRange').value; | |
| let emailText = `Subject: Servicio Claro - Alta Internet ${bandwidth} - N掳 Enlace: ${serviceNumber} ${client}\n\n`; | |
| emailText += `Estimado Cliente:\n\n`; | |
| emailText += `Le informamos que se ha realizado con 茅xito el ALTA a ${bandwidth} del servicio solicitado, ubicado en ${address}\n\n`; | |
| emailText += `Datos del servicio:\n`; | |
| emailText += `- Cliente: ${client}\n`; | |
| emailText += `- N掳 de enlace: ${serviceNumber}\n`; | |
| emailText += `- Domicilio: ${address}\n`; | |
| emailText += `- Ancho de banda: ${bandwidth}\n`; | |
| emailText += `- Rango IP: ${ipRange}\n\n`; | |
| // IP Table for email with better formatting | |
| emailText += `Detalle de configuraci贸n IP:\n\n`; | |
| // Calculate column widths | |
| const rows = ipTableBody.querySelectorAll('tr'); | |
| let maxTypeLength = 0; | |
| let maxIpLength = 0; | |
| let maxMaskLength = 0; | |
| rows.forEach(row => { | |
| const cells = row.querySelectorAll('td'); | |
| maxTypeLength = Math.max(maxTypeLength, cells[0].textContent.length); | |
| maxIpLength = Math.max(maxIpLength, cells[1].textContent.length); | |
| maxMaskLength = Math.max(maxMaskLength, cells[2].textContent.length); | |
| }); | |
| // Add padding to column headers | |
| const typeHeader = 'Tipo'.padEnd(maxTypeLength + 2); | |
| const ipHeader = 'Direcci贸n IP'.padEnd(maxIpLength + 2); | |
| const maskHeader = 'M谩scara'.padEnd(maxMaskLength + 2); | |
| // Table header | |
| emailText += `${typeHeader}${ipHeader}${maskHeader}\n`; | |
| emailText += `${'-'.repeat(typeHeader.length)}${'-'.repeat(ipHeader.length)}${'-'.repeat(maskHeader.length)}\n`; | |
| // Table rows | |
| rows.forEach(row => { | |
| const cells = row.querySelectorAll('td'); | |
| const type = cells[0].textContent.padEnd(maxTypeLength + 2); | |
| const ip = cells[1].textContent.padEnd(maxIpLength + 2); | |
| const mask = cells[2].textContent.padEnd(maxMaskLength + 2); | |
| emailText += `${type}${ip}${mask}\n`; | |
| }); | |
| emailText += `\n`; | |
| emailText += `Configuraci贸n DNS:\n`; | |
| emailText += `- DNS Primario: 186.12.238.16\n`; | |
| emailText += `- DNS Secundario: 186.12.238.15\n\n`; | |
| emailText += `Ante inconvenientes con la puesta en marcha, favor de comunicarse conmigo.\n`; | |
| emailText += `Posteriormente, por solicitudes o reclamos, Centro de Gesti贸n Empresarial gestionempresarial@claro.com.ar\n\n`; | |
| emailText += `Atte.\n`; | |
| emailOutput.textContent = emailText; | |
| feather.replace(); | |
| } | |
| function generateL2LEmail() { | |
| const client = document.getElementById('l2lClient').value; | |
| const serviceNumber = document.getElementById('l2lServiceNumber').value; | |
| const bandwidth = document.getElementById('l2lBandwidth').value; | |
| const siteAAddress = document.getElementById('siteAAddress').value; | |
| const siteADevice = document.getElementById('siteADevice').value; | |
| const siteAPort = document.getElementById('siteAPort').value; | |
| const siteBAddress = document.getElementById('siteBAddress').value; | |
| const siteBDevice = document.getElementById('siteBDevice').value; | |
| const siteBPort = document.getElementById('siteBPort').value; | |
| let emailText = `Subject: Servicio Claro - Alta L2L ${bandwidth} - N掳 Enlace: ${serviceNumber} ${client}\n\n`; | |
| emailText += `Estimado Cliente:\n\n`; | |
| emailText += `Le informamos que se ha realizado con 茅xito el ALTA a ${bandwidth} del servicio LAN to LAN solicitado.\n\n`; | |
| emailText += `Datos del servicio:\n`; | |
| emailText += `Cliente: ${client}\n`; | |
| emailText += `N掳 de enlace: ${serviceNumber}\n`; | |
| emailText += `Ancho de banda: ${bandwidth}\n\n`; | |
| emailText += `Detalle de extremos:\n\n`; | |
| // Calculate column widths for L2L table | |
| const siteALabelLength = Math.max('Direcci贸n:'.length, 'Equipo:'.length, 'Puerto:'.length); | |
| const siteBLabelLength = Math.max('Direcci贸n:'.length, 'Equipo:'.length, 'Puerto:'.length); | |
| const siteAContentLength = Math.max(siteAAddress.length, siteADevice.length, siteAPort.length); | |
| const siteBContentLength = Math.max(siteBAddress.length, siteBDevice.length, siteBPort.length); | |
| // Site A table | |
| emailText += `Extremo A:\n`; | |
| emailText += `${'Direcci贸n:'.padEnd(siteALabelLength + 2)}${siteAAddress.padEnd(siteAContentLength + 2)}\n`; | |
| emailText += `${'Equipo:'.padEnd(siteALabelLength + 2)}${siteADevice.padEnd(siteAContentLength + 2)}\n`; | |
| emailText += `${'Puerto:'.padEnd(siteALabelLength + 2)}${siteAPort.padEnd(siteAContentLength + 2)}\n\n`; | |
| // Site B table | |
| emailText += `Extremo B:\n`; | |
| emailText += `${'Direcci贸n:'.padEnd(siteBLabelLength + 2)}${siteBAddress.padEnd(siteBContentLength + 2)}\n`; | |
| emailText += `${'Equipo:'.padEnd(siteBLabelLength + 2)}${siteBDevice.padEnd(siteBContentLength + 2)}\n`; | |
| emailText += `${'Puerto:'.padEnd(siteBLabelLength + 2)}${siteBPort.padEnd(siteBContentLength + 2)}\n\n`; | |
| emailText += `Ante inconvenientes con la puesta en marcha, favor de comunicarse conmigo. Posteriormente, por solicitudes o reclamos, Centro de Gestion Empresarial gestionempresarial@claro.com.ar\n\n`; | |
| emailText += `Atte.-`; | |
| emailOutput.textContent = emailText; | |
| } | |
| }); |