From 18272c712e30ec056989b8575a59b0a18941a64f Mon Sep 17 00:00:00 2001 From: Borys_Levytskyi Date: Sat, 24 Apr 2021 13:10:41 +0300 Subject: [PATCH] Finilize VPC View support --- src/index.css | 26 ++-- src/networking/components/SubnetView.tsx | 4 +- src/networking/components/VpcView.css | 2 +- src/networking/components/VpcView.tsx | 164 ++++++++++++-------- src/networking/models.ts | 3 +- src/shell/AppState.ts | 10 +- src/shell/components/AppRoot.tsx | 2 +- src/shell/components/DebugIndicators.tsx | 2 +- src/shell/components/DisplayResultView.tsx | 25 ++- src/shell/components/HelpResultView.tsx | 1 + src/shell/components/Toggle.tsx | 9 +- src/shell/components/WhatsNewResultView.tsx | 8 + 12 files changed, 157 insertions(+), 99 deletions(-) diff --git a/src/index.css b/src/index.css index fde8741..a45dd8d 100644 --- a/src/index.css +++ b/src/index.css @@ -25,8 +25,8 @@ code { font-size: 1.2em; font-weight: bold; } .result .content { padding-left: 10px} .result .cur { margin-right: 5px; } -.hashLink { text-decoration: none; margin-left: 5px; visibility: hidden } -.hashLink:hover { text-decoration: underline; margin-left: 5px; } +.hashLink { text-decoration: none; margin-left: 5px; visibility: hidden; margin-right: 0; padding: 0; text-decoration: none; } +.hashLink:hover { text-decoration: underline; margin-left: 5px; background: none; } .result:hover .hashLink { visibility: visible } .expression .label { font-weight: bold; padding-right: 5px; text-align: right; } @@ -48,7 +48,7 @@ code { font-size: 1.2em; font-weight: bold; } .help ul { list-style-type: none; margin: 0; padding: 0; } .help p { margin-top: 0 } -.indicator { padding: 2px 5px; font-family: monospace; font-size: 1.3em; background: transparent; border: none; cursor: pointer } +.indicator { padding: 0px 5px; background: transparent; border: none; cursor: pointer; vertical-align: middle; } .error { color: maroon; } .soft { opacity: 0.7 } @@ -68,13 +68,13 @@ code { font-size: 1.2em; font-weight: bold; } .light .on { color: #121212; } .light .prefix { color: #888} .light .other { color: #bbb } -.light .hashLink, .light .hashLink:visited { color: #ddd } +.light .hashLink, .light .hashLink:visited { color: #ddd; } .light .hashLink:hover { color: #888 } .light ul.top-links li:hover { background: #ddd } .light .error { color: #da586d } -.light button { color: black} -.light button:hover { background: #ddd} -.light button:disabled { color: #888; background-color: inherit; } +.light button.btn { color: black} +.light button.btn:hover { background: #ddd} +.light button.btn:disabled { color: #888; background-color: inherit; } /* Dark */ .dark { background: #121212; color: white;} @@ -90,9 +90,9 @@ code { font-size: 1.2em; font-weight: bold; } .dark .hashLink:hover { color: #999 } .dark ul.top-links li:hover { background: #333 } .dark .error { color: #da586d} -.dark button { color: white} -.dark button:hover { background: #333} -.dark button:disabled { color: #999; background-color: inherit; } +.dark button.btn { color: white} +.dark button.btn:hover { background: #333} +.dark button.btn:disabled { color: #999; background-color: inherit; } /* Midnight Theme @@ -113,9 +113,9 @@ code { font-size: 1.2em; font-weight: bold; } .midnight ul.top-links li:hover { background: #132537 } .midnight .error { color:#da586d} .midnight .changelog .item-new .date { font-weight: bold } -.midnight button { color: white} -.midnight button:hover { background: #132537} -.midnight button:disabled { color: #85a0ad; background-color: inherit; } +.midnight button.btn { color: white} +.midnight button.btn:hover { background: #132537} +.midnight button.btn:disabled { color: #85a0ad; background-color: inherit; } button { border: none; diff --git a/src/networking/components/SubnetView.tsx b/src/networking/components/SubnetView.tsx index 169ffdc..5a303f8 100644 --- a/src/networking/components/SubnetView.tsx +++ b/src/networking/components/SubnetView.tsx @@ -41,9 +41,9 @@ function SubnetView(props : {subnet : SubnetCommand}) { - + {subnet.cidr.maskBits} - + diff --git a/src/networking/components/VpcView.css b/src/networking/components/VpcView.css index 835aa79..a7d1e34 100644 --- a/src/networking/components/VpcView.css +++ b/src/networking/components/VpcView.css @@ -32,7 +32,7 @@ } .vpc-view .address-space { - font-size: 1.5em; + font-size: 1.2em; vertical-align: middle; } diff --git a/src/networking/components/VpcView.tsx b/src/networking/components/VpcView.tsx index cac1e22..820a6b4 100644 --- a/src/networking/components/VpcView.tsx +++ b/src/networking/components/VpcView.tsx @@ -1,16 +1,18 @@ import React, { useState } from 'react'; import BinaryStringView from '../../core/components/BinaryString'; import './VpcView.css'; -import { getNetworkAddress, getBroadCastAddress, createSubnetMaskIp, getAddressSpaceSize } from '../subnet-utils'; -import { chunkifyString } from '../../core/utils'; +import { getNetworkAddress, getAddressSpaceSize } from '../subnet-utils'; import IpAddressBinaryString from './IpAddressBinaryString'; -import { IpAddress, IpAddressWithSubnetMask, SubnetCommand, VpcCommand } from '../models'; -import formatter, { padLeft } from '../../core/formatter'; +import { IpAddress, IpAddressWithSubnetMask, VpcCommand } from '../models'; +import formatter from '../../core/formatter'; +import Toggle from '../../shell/components/Toggle'; +import { faQuestionCircle } from '@fortawesome/free-solid-svg-icons'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; const MAX_NON_HOSTS_BITS = 30; // leave two bits for hosts min -function SubnetView(props : {vpc : VpcCommand}) { +function SubnetView(props: { vpc: VpcCommand }) { const [vpc, setVpc] = useState(VpcModel.create(props.vpc)); @@ -19,93 +21,107 @@ function SubnetView(props : {vpc : VpcCommand}) { 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 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 decrSubnet = () => 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 - -
- + +
+
VPC Network Address
- - - - {networkAddress.toString()} +
+ + + + {networkAddress.toString()} + setVpc(vpc.toggleLegend())} title="Show/Hide Color Legend"> + + +
+
+

+ Color Legend +

+ 000 - VPC address bits
+ 000 - Bits dedicated for subnets address
+ 000 - Bits dedicated to host addresses inside each subnet +
- - + + - + + + - - - - + + + - - - + + + - + + + - - - - - - - - - -
- VPC CIDR Mask: +
+ VPC CIDR Mask: - + + /{vpc.cidr.maskBits} - + +
+ Subnet CIDR Mask:
- Subnet CIDR Mask: - - + + /{subnetMaskSize} - + +
+ Max Subnets in VPC:
- Max Subnets in VPC: + + + {maxSubnets} + +
+ Max Hosts in VPC: - - {maxSubnets} - + + {maxSubnets * hostsPerSubnet} +
+ Hosts Per Subnet:
- Max Hosts in VPC: - - {maxSubnets*hostsPerSubnet} -
- Hosts Per Subnet: - - {hostsPerSubnet} -
+ + {hostsPerSubnet} + + + +
; } -function Indicator2(props: { ip: IpAddress, descr: string}) { +function Indicator2(props: { ip: IpAddress, descr: string }) { - const {ip, descr} = props; + const { ip, descr } = props; return - {descr} - - {ip.toString()} - - - - - ; + {descr} + + {ip.toString()} + + + + + ; } export default SubnetView; @@ -114,17 +130,23 @@ class VpcModel { cidr: IpAddressWithSubnetMask; subnetBits: number; subnetNum: number; - + showLegend: boolean; + constructor(cidr: IpAddressWithSubnetMask, subnetBits: number) { this.cidr = cidr; this.subnetBits = subnetBits; this.subnetNum = 0; + this.showLegend = false; } static create(vpc: VpcCommand) { return new VpcModel(vpc.cidr, vpc.subnetBits); } + clone() : VpcModel { + return Object.assign(new VpcModel(this.cidr, this.subnetBits), this); + } + changeSubnetBits(n: number) { return new VpcModel(this.cidr, n); } @@ -132,4 +154,10 @@ class VpcModel { changeVpcCidr(newCidr: IpAddressWithSubnetMask) { return new VpcModel(newCidr, this.subnetBits); } + + toggleLegend() { + var n = new VpcModel(this.cidr, this.subnetBits); + n.showLegend = !this.showLegend; + return n; + } } diff --git a/src/networking/models.ts b/src/networking/models.ts index cc53215..528385e 100644 --- a/src/networking/models.ts +++ b/src/networking/models.ts @@ -14,8 +14,7 @@ export class IpAddressWithSubnetMask { } getAdressSpaceSize(): number { - const spaceLengthInBits = 32 - this.maskBits; - return getAddressSpaceSize(spaceLengthInBits); + return getAddressSpaceSize(this.maskBits); } toString() { diff --git a/src/shell/AppState.ts b/src/shell/AppState.ts index bf77c13..3b10bb7 100644 --- a/src/shell/AppState.ts +++ b/src/shell/AppState.ts @@ -1,6 +1,6 @@ import log from 'loglevel'; -const APP_VERSION = 6; +const APP_VERSION = 7; export type PersistedAppData = { emphasizeBytes: boolean; @@ -59,6 +59,14 @@ export default class AppState { this.triggerChanged(); } + removeResult(index: number) { + if(index < 0 || index >= this.commandResults.length) + return; + + this.commandResults.splice(index, 1); + this.triggerChanged(); + } + toggleEmphasizeBytes() { this.emphasizeBytes = !this.emphasizeBytes; this.triggerChanged(); diff --git a/src/shell/components/AppRoot.tsx b/src/shell/components/AppRoot.tsx index c43d973..0857fbd 100644 --- a/src/shell/components/AppRoot.tsx +++ b/src/shell/components/AppRoot.tsx @@ -38,7 +38,7 @@ export default class AppRoot extends React.Component getResultViews() : JSX.Element[] { var results = this.state.commandResults.map((r, i) => - + {r.view} ); return results; diff --git a/src/shell/components/DebugIndicators.tsx b/src/shell/components/DebugIndicators.tsx index bff9364..a6c5d71 100644 --- a/src/shell/components/DebugIndicators.tsx +++ b/src/shell/components/DebugIndicators.tsx @@ -23,7 +23,7 @@ function DebugIndicators(props: {appState: AppState}) { return null; return
- {list.map(i => [{i.substring(0,1)}] )} + {list.map(i => [{i.substring(0,1)}] )}
} diff --git a/src/shell/components/DisplayResultView.tsx b/src/shell/components/DisplayResultView.tsx index 3cabf57..943e427 100644 --- a/src/shell/components/DisplayResultView.tsx +++ b/src/shell/components/DisplayResultView.tsx @@ -1,3 +1,5 @@ +import { faTrashAlt, faHashtag } from '@fortawesome/free-solid-svg-icons'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import React from 'react'; import AppState from '../AppState'; @@ -6,23 +8,32 @@ type DisplayResultProps = { appState: AppState, inputHash: string, input: string, - key: number, + resultKey: number, + resultIndex: number, onRemove?: (i: number) => void; } -export default class DisplayResultView extends React.Component { - render() { +const DisplayResultView: React.FunctionComponent = (props) => { + + const resultKey : number = props.resultKey; + const appState = props.appState; return
- >{this.props.input} - # + >{props.input} + + + +
- {this.props.children} + {props.children}
; - } } +export default DisplayResultView; + diff --git a/src/shell/components/HelpResultView.tsx b/src/shell/components/HelpResultView.tsx index 600390a..fb81ce4 100644 --- a/src/shell/components/HelpResultView.tsx +++ b/src/shell/components/HelpResultView.tsx @@ -20,6 +20,7 @@ function HelpResultView() {
  • — enter single or multiple ip addresses (separated by space) to see their binary represenation
  • — subnet mask notiations are support as well
  • — display information about subnet (network address, broadcast address, etc.)
  • +
  • — see how VPC network address bits are divided between VPC address, Subnets and Hosts
  • diff --git a/src/shell/components/Toggle.tsx b/src/shell/components/Toggle.tsx index 1ff9723..32b8de8 100644 --- a/src/shell/components/Toggle.tsx +++ b/src/shell/components/Toggle.tsx @@ -2,18 +2,21 @@ import React from "react"; export type ToggleProps = { - text: string, + text?: string, isOn: boolean, title: string, elementId?: string onClick: () => void }; -function Toggle(props: ToggleProps) { +const Toggle: React.FunctionComponent = (props) => { + return props.onClick()}>{props.text} + onClick={() => props.onClick()}> + { !props.children ? props.text : props.children } + } function getIndicator(value : boolean) { diff --git a/src/shell/components/WhatsNewResultView.tsx b/src/shell/components/WhatsNewResultView.tsx index cdab352..57d6230 100644 --- a/src/shell/components/WhatsNewResultView.tsx +++ b/src/shell/components/WhatsNewResultView.tsx @@ -7,6 +7,14 @@ function WhatsnewResultView() { return

    Changelog

    +

    Jul 24th, 2021
    +

      +
    • Added support of vpc command to see hpw VPC network address is divided bettwen VPC, Subnets and Hosts. Try it out:
    • +
    • Added ability to remove individual results
    • +
    +

    +
    +

    Jun 16th, 2021
    Added support of subnet command to display information about subnet ip adress such. Try it out: