Improve VPC view

This commit is contained in:
Borys_Levytskyi
2021-04-24 11:08:37 +03:00
parent cb28d5ecc0
commit 03b33614ad
7 changed files with 98 additions and 25 deletions

View File

@@ -5,7 +5,8 @@ export type BinaryStringViewProps = {
binaryString: string;
onFlipBit?: (input: FlipBitEventArg) => void;
emphasizeBytes?: boolean;
className?:string
className?:string;
disableHighlight?:boolean
};
export type FlipBitEventArg = {
@@ -50,8 +51,15 @@ export default class BinaryStringView extends React.Component<BinaryStringViewPr
const allowFlipBits = this.props.allowFlipBits || false;
const css = allowFlipBits ? ' flipable' : ''
const disableHighlight = this.props.disableHighlight || false;
return bitChars.map((c, i) => {
var className = c == '1' ? `one${css}` : `zero${css}`;
if(disableHighlight)
className = css;
return <span className={className} key={i} onClick={e => this.onBitClick(i, e)}>{c}</span>
});
}

View File

@@ -10,4 +10,11 @@ describe("formatter", () => {
it('pads left', () => {
expect(formatter.padLeft("1", 3, " ")).toBe(" 1");
});
it('splits ip address by mask', () => {
const ip = "11000000.10101000.00000001.00000001";
expect(formatter.splitByMasks(ip, 2, 3)).toEqual({vpc:"11", subnet:"0", hosts:"00000.10101000.00000001.00000001"});
expect(formatter.splitByMasks(ip, 8, 16)).toEqual({vpc:"11000000", subnet:".10101000", hosts:".00000001.00000001"});
expect(formatter.splitByMasks(ip, 8, 22)).toEqual({vpc:"11000000", subnet:".10101000.000000", hosts:"01.00000001"});
})
});

View File

@@ -20,6 +20,35 @@ const formatter = {
},
emBin(number: number) {
return this.padLeft(this.bin(number), 8, '0');
},
splitByMasks(ipAddrBin: string, mask1: number, mask2: number) : {vpc: string, subnet: string, hosts:string} {
var res = [];
var tmp : string[] = [];
var mask = 0;
var b = mask1;
ipAddrBin.split('').forEach(ch => {
tmp.push(ch);
if(ch === ".") {
return;
}
mask++;
if(mask == b) {
b = mask2;
res.push(tmp.join(''));
tmp = [];
}
});
if(tmp.length > 0) res.push(tmp.join(''));
return { vpc: res[0], subnet: res[1], hosts: res[2]};
}
};

View File

@@ -11,28 +11,28 @@ function SubnetView(props : {subnet : SubnetCommand}) {
const [subnet, setSubnet] = useState(props.subnet);
const incrementMask = () => {
const newInput = new IpAddressWithSubnetMask(subnet.input.ipAddress, subnet.input.maskBits+1);
const newInput = new IpAddressWithSubnetMask(subnet.cidr.ipAddress, subnet.cidr.maskBits+1);
setSubnet(new SubnetCommand(newInput));
};
const decrementMask = () => {
const newInput = new IpAddressWithSubnetMask(subnet.input.ipAddress, subnet.input.maskBits-1);
const newInput = new IpAddressWithSubnetMask(subnet.cidr.ipAddress, subnet.cidr.maskBits-1);
setSubnet(new SubnetCommand(newInput));
}
return <React.Fragment>
<table className="expression subnet-view">
<tbody>
<SubnetRow ip={subnet.input.ipAddress} descr="Address"/>
<SubnetRow ip={getNetworkAddress(subnet.input)} descr="Network"/>
<SubnetRow ip={createSubnetMaskIp(subnet.input)} descr="Net Mask"/>
<SubnetRow ip={getBroadCastAddress(subnet.input)} descr="Broadcast"/>
<SubnetRow ip={subnet.cidr.ipAddress} descr="Address"/>
<SubnetRow ip={getNetworkAddress(subnet.cidr)} descr="Network"/>
<SubnetRow ip={createSubnetMaskIp(subnet.cidr)} descr="Net Mask"/>
<SubnetRow ip={getBroadCastAddress(subnet.cidr)} descr="Broadcast"/>
<tr>
<td data-test-name="label" className="soft">
<span>Network Size</span>
</td>
<td data-test-name="decimal">
{subnet.input.getAdressSpaceSize()}
{subnet.cidr.getAdressSpaceSize()}
</td>
</tr>
<tr>
@@ -41,9 +41,9 @@ function SubnetView(props : {subnet : SubnetCommand}) {
</td>
<td data-test-name="decimal">
<button onClick={decrementMask} disabled={subnet.input.maskBits === 0} title="Decrease mask size">-</button>
<span>{subnet.input.maskBits}</span>
<button onClick={incrementMask} disabled={subnet.input.maskBits === 32} title="Increase mask size">+</button>
<button onClick={decrementMask} disabled={subnet.cidr.maskBits === 0} title="Decrease mask size">-</button>
<span>{subnet.cidr.maskBits}</span>
<button onClick={incrementMask} disabled={subnet.cidr.maskBits === 32} title="Increase mask size">+</button>
</td>
</tr>
</tbody>

View File

@@ -7,6 +7,18 @@
margin-bottom: 20px;
}
.vpc-view {
margin-bottom: 20px;
}
.vpc-view .host-part {
color: teal;
}
.vpc-view .subnet-part {
color:mediumseagreen;
}
.vpc-view .part {
border-bottom: solid 1px;
}

View File

@@ -5,10 +5,14 @@ import { getNetworkAddress, getBroadCastAddress, createSubnetMaskIp, getAddressS
import { chunkifyString } from '../../core/utils';
import IpAddressBinaryString from './IpAddressBinaryString';
import { IpAddress, IpAddressWithSubnetMask, SubnetCommand, VpcCommand } from '../models';
import { padLeft } from '../../core/formatter';
import formatter, { padLeft } from '../../core/formatter';
type ViewMode = "color" | "table";
function SubnetView(props : {vpc : VpcCommand}) {
const mode : ViewMode = "color";
const [vpc, setVpc] = useState(VpcModel.create(props.vpc));
const subnetMaskSize = vpc.cidr.maskBits + vpc.subnetBits;
@@ -17,15 +21,25 @@ function SubnetView(props : {vpc : VpcCommand}) {
const lastPart = padLeft("0", 32 - (vpc.cidr.maskBits + vpc.subnetBits), "0");
const maxSubnets = Math.pow(2, vpc.subnetBits);
const hostsPerSubnet = getAddressSpaceSize(subnetMaskSize);
const networkAddress = getNetworkAddress(vpc.cidr);
const decrSubnet = () => setVpc(vpc.changeSubnetBits(vpc.subnetBits-1));
const incrSubnet = () => setVpc(vpc.changeSubnetBits(vpc.subnetBits+1));
const incrSubnet = () => setVpc(vpc.changeSubnetBits(vpc.subnetBits+1));
const incrVpc = () => setVpc(vpc.changeVpcCidr(new IpAddressWithSubnetMask(vpc.cidr.ipAddress, vpc.cidr.maskBits+1)));
const decrVpc = () => setVpc(vpc.changeVpcCidr(new IpAddressWithSubnetMask(vpc.cidr.ipAddress, vpc.cidr.maskBits-1)));
const split = formatter.splitByMasks(networkAddress.toBinaryString(), vpc.cidr.maskBits, subnetMaskSize);
return <React.Fragment>
<div className="expression vpc-view">
<div>
<div style={{display: mode === "color" ? '': 'none'}}>
<BinaryStringView binaryString={split.vpc} disableHighlight={true} className="address-space soft" />
<BinaryStringView binaryString={split.subnet} disableHighlight={true} className="address-space subnet-part"/>
<BinaryStringView binaryString={split.hosts} disableHighlight={true} className="address-space host-part" />
</div>
<div style={{display: mode === "color" ? 'none': ''}}>
<table>
<tr>
<td className="address-space-label">
@@ -42,12 +56,12 @@ function SubnetView(props : {vpc : VpcCommand}) {
<td>
<button onClick={decrVpc} disabled={vpc.cidr.maskBits <= 1} title="Increase vpc space">-</button>
<BinaryStringView binaryString={vpcPart} className="address-space" />
<button onClick={incrVpc} disabled={subnetMaskSize >= 31} title="Decrease vpc space">+</button>
<button onClick={incrVpc} disabled={subnetMaskSize >= 30} title="Decrease vpc space">+</button>
</td>
<td>
<button onClick={decrSubnet} disabled={vpc.subnetBits <= 1} title="Increase subnet space">-</button>
<BinaryStringView binaryString={subnetsPart} className="address-space" />
<button onClick={incrSubnet} disabled={vpc.cidr.maskBits + vpc.subnetBits >= 31} title="Decrease subnet space">+</button>
<button onClick={incrSubnet} disabled={vpc.cidr.maskBits + vpc.subnetBits >= 30} title="Decrease subnet space">+</button>
</td>
<td>
<BinaryStringView binaryString={lastPart} className="address-space" />
@@ -70,15 +84,19 @@ function SubnetView(props : {vpc : VpcCommand}) {
VPC CIDR Mask:
</td>
<td>
/{vpc.cidr.maskBits}
<button onClick={decrVpc} disabled={vpc.cidr.maskBits <= 1} title="Increase vpc space">-</button>
/{vpc.cidr.maskBits}
<button onClick={incrVpc} disabled={subnetMaskSize >= 30} title="Decrease vpc space">+</button>
</td>
</tr>
<tr>
<td className="soft">
Subnet CIDR Mask:
<td className="soft">
Subnet CIDR Mask:
</td>
<td>
/{subnetMaskSize}
<button onClick={decrSubnet} disabled={vpc.subnetBits <= 1} title="Increase subnet space">-</button>
/{subnetMaskSize}
<button onClick={incrSubnet} disabled={vpc.cidr.maskBits + vpc.subnetBits >= 30} title="Decrease subnet space">+</button>
</td>
</tr>
<tr>

View File

@@ -1,5 +1,4 @@
import {emBin} from "../core/formatter";
import { numberParser } from "../expression/numberParser";
import { getAddressSpaceSize } from "./subnet-utils";
export type OctetNumber = 1 | 2 | 3 | 4;
@@ -73,13 +72,13 @@ export class IpAddress {
}
export class SubnetCommand {
input: IpAddressWithSubnetMask; // TODO: rename to cidr
constructor(definition: IpAddressWithSubnetMask) {
this.input = definition;
cidr: IpAddressWithSubnetMask; // TODO: rename to cidr
constructor(cidr: IpAddressWithSubnetMask) {
this.cidr = cidr;
}
toString() {
return this.input.toString();
return this.cidr.toString();
}
}