Merge branch 'release/v0.5'
This commit is contained in:
commit
926a188d4a
3 changed files with 151 additions and 16 deletions
30
dist/index.html
vendored
30
dist/index.html
vendored
|
@ -24,23 +24,23 @@
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<h1>Visual Subnet Calculator <span style="font-size:1rem;">(UNDER CONSTRUCTION)</span></h1>
|
<h1>Visual Subnet Calculator <span style="font-size:1rem;">(UNDER CONSTRUCTION)</span></h1>
|
||||||
<div class="alert alert-primary alert-dismissible show mt-3" role="alert">
|
<div class="alert alert-primary alert-dismissible show mt-3" role="alert">
|
||||||
Enter the network you wish to subnet and use the Split/Join buttons on the right to start designing!
|
Enter the network you wish to subnet and use the Split/Join buttons on the right to start designing!
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row font-monospace g-2 mb-3">
|
<form id="input_form" class="row font-monospace g-2 mb-3" novalidate>
|
||||||
<div class="col-lg-2 col-md-3 col-4">
|
<div class="col-lg-2 col-md-3 col-4">
|
||||||
<div><label for="basic-url" class="form-label mb-0 ms-1">Network Address</label></div>
|
<div><label for="network" class="form-label mb-0 ms-1">Network Address</label></div>
|
||||||
<div><input id="network" type="text" class="form-control" value="10.0.0.0" aria-label="Network Address"></div>
|
<div><input id="network" type="text" class="form-control" value="10.0.0.0" aria-label="Network Address" pattern="^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)" required></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-auto">
|
<div class="col-auto">
|
||||||
<div style="height:2rem"></div>
|
<div style="height:2rem"></div>
|
||||||
<div>/</div>
|
<div>/</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-lg-2 col-md-3 col-4">
|
<div class="col-lg-2 col-md-3 col-4">
|
||||||
<div><label for="basic-url" class="form-label mb-0 ms-1">Network Size</label></div>
|
<div><label for="netsize" class="form-label mb-0 ms-1">Network Size</label></div>
|
||||||
<div><input id="netsize" type="text" class="form-control w-10" value="16" aria-label="Network Size"></div>
|
<div><input id="netsize" type="text" class="form-control w-10" value="16" aria-label="Network Size" pattern="^(\d|[12]\d|30)$" required></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-lg-2 col-md-3 col-3">
|
<div class="col-lg-2 col-md-3 col-3">
|
||||||
<div style="height:1.5rem"></div>
|
<div style="height:1.5rem"></div>
|
||||||
|
@ -49,7 +49,7 @@
|
||||||
<button id="btn_reset" class="btn btn-danger mb-0 mt-auto" type="button">Reset</button>
|
<button id="btn_reset" class="btn btn-danger mb-0 mt-auto" type="button">Reset</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</form>
|
||||||
|
|
||||||
|
|
||||||
<table id="calc" class="table table-bordered font-monospace">
|
<table id="calc" class="table table-bordered font-monospace">
|
||||||
|
@ -81,6 +81,22 @@
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
<div class="modal fade" id="notifyModal" tabindex="-1" aria-labelledby="notifyModalLabel" aria-hidden="true">
|
||||||
|
<div class="modal-dialog modal-md">
|
||||||
|
<div class="modal-content alert-warning">
|
||||||
|
<div class="modal-header border-bottom-0 pb-1">
|
||||||
|
<h3 class="modal-title" id="notifyModalLabel">Warning!</h3>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body pt-1">
|
||||||
|
Notification Text Here
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div class="modal fade" id="aboutModal" tabindex="-1" aria-labelledby="aboutModalLabel" aria-hidden="true">
|
<div class="modal fade" id="aboutModal" tabindex="-1" aria-labelledby="aboutModalLabel" aria-hidden="true">
|
||||||
<div class="modal-dialog modal-xl modal-dialog-centered">
|
<div class="modal-dialog modal-xl modal-dialog-centered">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
|
|
4
dist/main.css
vendored
4
dist/main.css
vendored
|
@ -62,6 +62,10 @@
|
||||||
font-size:1rem;
|
font-size:1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#notifyModal .modal-content {
|
||||||
|
background-color: var(--bs-alert-bg);
|
||||||
|
}
|
||||||
|
|
||||||
#calc td.join {
|
#calc td.join {
|
||||||
background-color: var(--join-background);
|
background-color: var(--join-background);
|
||||||
color: var(--join-foreground);
|
color: var(--join-foreground);
|
||||||
|
|
133
dist/main.js
vendored
133
dist/main.js
vendored
|
@ -1,6 +1,27 @@
|
||||||
let subnetMap = {};
|
let subnetMap = {};
|
||||||
|
let subnetNotes = {};
|
||||||
let maxNetSize = 0;
|
let maxNetSize = 0;
|
||||||
let infoColumnCount = 5
|
let infoColumnCount = 5
|
||||||
|
// NORMAL mode:
|
||||||
|
// - Smallest subnet: /30
|
||||||
|
// - Two reserved addresses per subnet:
|
||||||
|
// - Network Address (network + 0)
|
||||||
|
// - Broadcast Address (last network address)
|
||||||
|
// AWS mode (future):
|
||||||
|
// - Smallest subnet: /28
|
||||||
|
// - Two reserved addresses per subnet:
|
||||||
|
// - Network Address (network + 0)
|
||||||
|
// - AWS Reserved - VPC Router
|
||||||
|
// - AWS Reserved - VPC DNS
|
||||||
|
// - AWS Reserved - Future Use
|
||||||
|
// - Broadcast Address (last network address)
|
||||||
|
let operatingMode = 'NORMAL'
|
||||||
|
let noteTimeout;
|
||||||
|
|
||||||
|
$('input#network,input#netsize').on('input', function() {
|
||||||
|
$('#input_form')[0].classList.add('was-validated');
|
||||||
|
})
|
||||||
|
|
||||||
$('#btn_go').on('click', function() {
|
$('#btn_go').on('click', function() {
|
||||||
reset();
|
reset();
|
||||||
})
|
})
|
||||||
|
@ -10,7 +31,13 @@ $('#btn_reset').on('click', function() {
|
||||||
})
|
})
|
||||||
|
|
||||||
function reset() {
|
function reset() {
|
||||||
let rootCidr = get_network($('#network').val(), $('#netsize').val()) + '/' + $('#netsize').val()
|
let cidrInput = $('#network').val() + '/' + $('#netsize').val()
|
||||||
|
let rootNetwork = get_network($('#network').val(), $('#netsize').val())
|
||||||
|
let rootCidr = rootNetwork + '/' + $('#netsize').val()
|
||||||
|
if (cidrInput !== rootCidr) {
|
||||||
|
show_warning_modal('<div>Your network input is not on a network boundary for this network size. It has been automatically changed:</div><div class="font-monospace pt-2">' + $('#network').val() + ' -> ' + rootNetwork + '</div>')
|
||||||
|
}
|
||||||
|
$('#network').val(rootNetwork)
|
||||||
subnetMap = {}
|
subnetMap = {}
|
||||||
subnetMap[rootCidr] = {}
|
subnetMap[rootCidr] = {}
|
||||||
maxNetSize = parseInt($('#netsize').val())
|
maxNetSize = parseInt($('#netsize').val())
|
||||||
|
@ -63,11 +90,28 @@ function reset() {
|
||||||
|
|
||||||
$('#calcbody').on('click', 'td.split,td.join', function(event) {
|
$('#calcbody').on('click', 'td.split,td.join', function(event) {
|
||||||
// HTML DOM Data elements! Yay! See the `data-*` attributes of the HTML tags
|
// HTML DOM Data elements! Yay! See the `data-*` attributes of the HTML tags
|
||||||
console.log(this.dataset.subnet)
|
|
||||||
mutate_subnet_map(this.dataset.mutateVerb, this.dataset.subnet, subnetMap)
|
mutate_subnet_map(this.dataset.mutateVerb, this.dataset.subnet, subnetMap)
|
||||||
renderTable();
|
renderTable();
|
||||||
})
|
})
|
||||||
|
|
||||||
|
$('#calcbody').on('keyup', 'td.note input', function(event) {
|
||||||
|
// HTML DOM Data elements! Yay! See the `data-*` attributes of the HTML tags
|
||||||
|
let delay = 1000;
|
||||||
|
clearTimeout(noteTimeout);
|
||||||
|
noteTimeout = setTimeout(function(element) {
|
||||||
|
console.log('CAP')
|
||||||
|
subnetNotes[element.dataset.subnet] = element.value
|
||||||
|
}, delay, this);
|
||||||
|
})
|
||||||
|
|
||||||
|
$('#calcbody').on('focusout', 'td.note input', function(event) {
|
||||||
|
// HTML DOM Data elements! Yay! See the `data-*` attributes of the HTML tags
|
||||||
|
clearTimeout(noteTimeout);
|
||||||
|
console.log('CAP')
|
||||||
|
subnetNotes[this.dataset.subnet] = this.value
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
function renderTable() {
|
function renderTable() {
|
||||||
// TODO: Validation Code
|
// TODO: Validation Code
|
||||||
$('#calcbody').empty();
|
$('#calcbody').empty();
|
||||||
|
@ -100,7 +144,7 @@ function addRow(network, netSize, colspan) {
|
||||||
' <td class="row_range">' + int2ip(addressFirst) + ' - ' + int2ip(addressLast) + '</td>\n' +
|
' <td class="row_range">' + int2ip(addressFirst) + ' - ' + int2ip(addressLast) + '</td>\n' +
|
||||||
' <td class="row_usable">' + int2ip(usableFirst) + ' - ' + int2ip(usableLast) + '</td>\n' +
|
' <td class="row_usable">' + int2ip(usableFirst) + ' - ' + int2ip(usableLast) + '</td>\n' +
|
||||||
' <td class="row_hosts">' + hostCount + '</td>\n' +
|
' <td class="row_hosts">' + hostCount + '</td>\n' +
|
||||||
' <td class="note"><label><input type="text" class="form-control shadow-none p-0"></label></td>\n' +
|
' <td class="note"><label><input type="text" class="form-control shadow-none p-0" data-subnet="' + network + '/' + netSize + '" value="' + (subnetNotes[network + '/' + netSize] || '') + '"></label></td>\n' +
|
||||||
' <td rowspan="1" colspan="' + colspan + '" class="split rotate" data-subnet="' + network + '/' + netSize + '" data-mutate-verb="split"><span>/' + netSize + '</span></td>\n'
|
' <td rowspan="1" colspan="' + colspan + '" class="split rotate" data-subnet="' + network + '/' + netSize + '" data-mutate-verb="split"><span>/' + netSize + '</span></td>\n'
|
||||||
if (netSize > maxNetSize) {
|
if (netSize > maxNetSize) {
|
||||||
// This is wrong. Need to figure out a way to get the number of children so you can set rowspan and the number
|
// This is wrong. Need to figure out a way to get the number of children so you can set rowspan and the number
|
||||||
|
@ -118,8 +162,6 @@ function addRow(network, netSize, colspan) {
|
||||||
newRow += ' </tr>';
|
newRow += ' </tr>';
|
||||||
|
|
||||||
$('#calcbody').append(newRow)
|
$('#calcbody').append(newRow)
|
||||||
console.log(network)
|
|
||||||
console.log(netSize)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -213,10 +255,26 @@ function mutate_subnet_map(verb, network, subnetTree) {
|
||||||
if (mapKey === network) {
|
if (mapKey === network) {
|
||||||
if (verb === 'split') {
|
if (verb === 'split') {
|
||||||
let netSplit = mapKey.split('/')
|
let netSplit = mapKey.split('/')
|
||||||
let new_networks = split_network(netSplit[0], parseInt(netSplit[1]))
|
// operatingMode NORMAL
|
||||||
subnetTree[mapKey][new_networks[0]] = {}
|
let minSubnetSize = 30
|
||||||
subnetTree[mapKey][new_networks[1]] = {}
|
if (operatingMode === 'AWS') {
|
||||||
|
minSubnetSize = 28
|
||||||
|
}
|
||||||
|
if (parseInt(netSplit[1]) < minSubnetSize) {
|
||||||
|
let new_networks = split_network(netSplit[0], parseInt(netSplit[1]))
|
||||||
|
subnetTree[mapKey][new_networks[0]] = {}
|
||||||
|
subnetTree[mapKey][new_networks[1]] = {}
|
||||||
|
// Copy note to both children and delete Delete parent note
|
||||||
|
subnetNotes[new_networks[0]] = subnetNotes[mapKey]
|
||||||
|
subnetNotes[new_networks[1]] = subnetNotes[mapKey]
|
||||||
|
delete subnetNotes[mapKey]
|
||||||
|
}
|
||||||
} else if (verb === 'join') {
|
} else if (verb === 'join') {
|
||||||
|
// Keep the note of the first subnet (which matches the network address) and lose the second subnet's note
|
||||||
|
// Could consider changing this to concatenate the notes into the parent, but I think this is more intuitive
|
||||||
|
subnetNotes[mapKey] = subnetNotes[Object.keys(subnetTree[mapKey])[0]]
|
||||||
|
subnetNotes[Object.keys(subnetTree[mapKey])[0]] = ''
|
||||||
|
subnetNotes[Object.keys(subnetTree[mapKey])[1]] = ''
|
||||||
subnetTree[mapKey] = {}
|
subnetTree[mapKey] = {}
|
||||||
} else {
|
} else {
|
||||||
// How did you get here?
|
// How did you get here?
|
||||||
|
@ -224,7 +282,64 @@ function mutate_subnet_map(verb, network, subnetTree) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
function validate_cidr(network, netSize) {
|
||||||
|
let returnObj = {
|
||||||
|
'valid': false,
|
||||||
|
'errorNetwork': true,
|
||||||
|
'errorSize': true,
|
||||||
|
'cidr': false,
|
||||||
|
'network': false,
|
||||||
|
'netSize': false
|
||||||
|
}
|
||||||
|
returnObj['network'] = validate_network(network)
|
||||||
|
if (returnObj['network']) {
|
||||||
|
returnObj['errorNetwork'] = false;
|
||||||
|
}
|
||||||
|
if (!/^\d+$/.test(netSize)) {
|
||||||
|
returnObj['errorSize'] = true;
|
||||||
|
} else {
|
||||||
|
netSize = parseInt(netSize)
|
||||||
|
if ((netSize > 32) || (netSize < 0)) {
|
||||||
|
returnObj['errorSize'] = true;
|
||||||
|
} else {
|
||||||
|
returnObj['errorSize'] = false;
|
||||||
|
returnObj['netSize'] = netSize.toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((returnObj['errorNetwork'] === false) && (returnObj['errorSize'] === false)) {
|
||||||
|
returnObj['cidr'] = returnObj['network'] + '/' + returnObj['netSize']
|
||||||
|
returnObj['valid'] = true
|
||||||
|
}
|
||||||
|
return returnObj;
|
||||||
|
}
|
||||||
|
|
||||||
|
function validate_network(network) {
|
||||||
|
// This can probably be done with Regex but this is better.
|
||||||
|
let octets = network.split('.');
|
||||||
|
if (octets.length !== 4) { return false }
|
||||||
|
if (!/^\d+$/.test(octets[0])) { return false }
|
||||||
|
if (!/^\d+$/.test(octets[1])) { return false }
|
||||||
|
if (!/^\d+$/.test(octets[2])) { return false }
|
||||||
|
if (!/^\d+$/.test(octets[3])) { return false }
|
||||||
|
octets[0] = parseInt(octets[0])
|
||||||
|
octets[1] = parseInt(octets[1])
|
||||||
|
octets[2] = parseInt(octets[2])
|
||||||
|
octets[3] = parseInt(octets[3])
|
||||||
|
if ((octets[0] < 0) || (octets[0] > 255)) { return false }
|
||||||
|
if ((octets[1] < 0) || (octets[1] > 255)) { return false }
|
||||||
|
if ((octets[2] < 0) || (octets[2] > 255)) { return false }
|
||||||
|
if ((octets[3] < 0) || (octets[3] > 255)) { return false }
|
||||||
|
return octets.join('.')
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
function show_warning_modal(message) {
|
||||||
|
var notifyModal = new bootstrap.Modal(document.getElementById("notifyModal"), {});
|
||||||
|
$('#notifyModal .modal-body').html(message)
|
||||||
|
notifyModal.show()
|
||||||
|
}
|
||||||
|
|
||||||
$( document ).ready(function() {
|
$( document ).ready(function() {
|
||||||
reset();
|
reset();
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue