link to bgp tools for asns, updated tables and modal
This commit is contained in:
parent
0853cb83de
commit
4db0f92816
12
ui/src/app/components/asns/AsPath.js
Normal file
12
ui/src/app/components/asns/AsPath.js
Normal file
@ -0,0 +1,12 @@
|
||||
|
||||
import AsnLink
|
||||
from 'app/components/asns/AsnLink';
|
||||
|
||||
/**
|
||||
* Render an AS path as a list of links to ASNs.
|
||||
*/
|
||||
const AsPath = ({ asns }) => asns.map((asn, i) => (
|
||||
[<AsnLink key={i} asn={asn} />, " "]
|
||||
));
|
||||
|
||||
export default AsPath;
|
14
ui/src/app/components/asns/AsnLink.js
Normal file
14
ui/src/app/components/asns/AsnLink.js
Normal file
@ -0,0 +1,14 @@
|
||||
|
||||
/**
|
||||
* Wrap an ASNumber with a link to bgp.tools for more information.
|
||||
*/
|
||||
const AsnLink = ({ asn }) => {
|
||||
// const baseUrl = "https://irrexplorer.nlnog.net/asn/AS";
|
||||
const baseUrl = "https://bgp.tools/as/";
|
||||
const url = `${baseUrl}${asn}`;
|
||||
return (
|
||||
<a href={url} target="_blank" rel="noreferrer">{asn}</a>
|
||||
);
|
||||
}
|
||||
|
||||
export default AsnLink;
|
@ -34,6 +34,8 @@ import { isUpState }
|
||||
from 'app/components/neighbors/state';
|
||||
import RelativeTimestamp
|
||||
from 'app/components/datetime/RelativeTimestamp';
|
||||
import AsnLink
|
||||
from 'app/components/asns/AsnLink';
|
||||
|
||||
/**
|
||||
* Default: Sort by ASN, ascending order.
|
||||
@ -238,6 +240,12 @@ const ColPlain = ({neighbor, column}) => {
|
||||
);
|
||||
}
|
||||
|
||||
const ColAsn = ({neighbor}) => {
|
||||
return (
|
||||
<td><AsnLink asn={neighbor.asn} /></td>
|
||||
);
|
||||
}
|
||||
|
||||
const ColNotAvailable = () => {
|
||||
return <td>-</td>;
|
||||
}
|
||||
@ -247,7 +255,7 @@ const NeighborColumn = ({neighbor, column}) => {
|
||||
const rs = useRouteServer();
|
||||
const widgets = {
|
||||
// Special cases
|
||||
"asn": ColPlain,
|
||||
"asn": ColAsn,
|
||||
"state": ColPlain,
|
||||
|
||||
"Uptime": ColUptime,
|
||||
|
56
ui/src/app/components/routes/Age.js
Normal file
56
ui/src/app/components/routes/Age.js
Normal file
@ -0,0 +1,56 @@
|
||||
|
||||
import { useMemo }
|
||||
from 'react';
|
||||
|
||||
import { useApiStatus }
|
||||
from 'app/context/api-status';
|
||||
|
||||
|
||||
import RelativeTimestampFormat
|
||||
from 'app/components/datetime/RelativeTimestampFormat';
|
||||
import RelativeTimestamp
|
||||
from 'app/components/datetime/RelativeTimestamp';
|
||||
|
||||
export const RouteAgeDetails = ({route}) => {
|
||||
const api = useApiStatus();
|
||||
|
||||
return useMemo(() =>
|
||||
<>
|
||||
<RelativeTimestampFormat
|
||||
value={route.age}
|
||||
now={api.receivedAt}
|
||||
format="YYYY-MM-DD HH:mm:ss"/> UTC
|
||||
<b> (<RelativeTimestamp
|
||||
value={route.age}
|
||||
now={api.receivedAt}
|
||||
suffix={true} />)
|
||||
</b>
|
||||
</>,
|
||||
[route.age, api.receivedAt]
|
||||
);
|
||||
}
|
||||
|
||||
export const RouteAgeRelative = ({route}) => {
|
||||
const api = useApiStatus();
|
||||
|
||||
return useMemo(() =>
|
||||
<RelativeTimestamp
|
||||
value={route.age}
|
||||
now={api.receivedAt}
|
||||
suffix={true} />,
|
||||
[route.age, api.receivedAt]
|
||||
);
|
||||
}
|
||||
|
||||
export const RouteAgeAbsolute = ({route}) => {
|
||||
const api = useApiStatus();
|
||||
|
||||
return useMemo(() =>
|
||||
<><RelativeTimestampFormat
|
||||
value={route.age}
|
||||
now={api.receivedAt}
|
||||
format="YYYY-MM-DD HH:mm:ss"/> UTC</>
|
||||
, [route.age, api.receivedAt]
|
||||
);
|
||||
}
|
||||
|
@ -14,11 +14,10 @@ import { Modal
|
||||
from 'app/components/modal/Modal';
|
||||
import BgpCommunitiyLabel
|
||||
from 'app/components/routes/BgpCommunityLabel';
|
||||
import RelativeTimestampFormat
|
||||
from 'app/components/datetime/RelativeTimestampFormat';
|
||||
import RelativeTimestamp
|
||||
from 'app/components/datetime/RelativeTimestamp';
|
||||
|
||||
import { RouteAgeDetails }
|
||||
from 'app/components/routes/Age';
|
||||
import AsPath
|
||||
from 'app/components/asns/AsPath';
|
||||
|
||||
const RouteDetailsModal = () => {
|
||||
const [ route, setRoute ] = useRouteDetails();
|
||||
@ -56,17 +55,10 @@ const RouteDetailsModal = () => {
|
||||
<table className="table table-nolines">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>Age:</th><td>
|
||||
<RelativeTimestampFormat
|
||||
value={route.age}
|
||||
now={api.receivedAt}
|
||||
format="YYYY-MM-DD HH:mm:ss"/> UTC
|
||||
<b> (<RelativeTimestamp
|
||||
value={route.age}
|
||||
now={api.receivedAt}
|
||||
suffix={true} />)
|
||||
</b>
|
||||
</td>
|
||||
<th>Age:</th>
|
||||
<td>
|
||||
<RouteAgeDetails route={route} />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Origin:</th><td>{attrs.origin}</td>
|
||||
@ -83,7 +75,8 @@ const RouteDetailsModal = () => {
|
||||
</tr>
|
||||
{attrs.as_path &&
|
||||
<tr>
|
||||
<th>AS Path:</th><td>{attrs.as_path.join(' ')}</td>
|
||||
<th>AS Path:</th>
|
||||
<td><AsPath asns={attrs.as_path} /></td>
|
||||
</tr>}
|
||||
{communities.length > 0 &&
|
||||
<tr>
|
||||
|
@ -24,6 +24,12 @@ import BlackholeIndicator
|
||||
from 'app/components/routes/flags/BlackholeIndicator';
|
||||
import RejectCandidateIndicator
|
||||
from 'app/components/routes/flags/RejectCandidateIndicator';
|
||||
import AsPath
|
||||
from 'app/components/asns/AsPath';
|
||||
import AsnLink
|
||||
from 'app/components/asns/AsnLink';
|
||||
import { RouteAgeRelative }
|
||||
from 'app/components/routes/Age';
|
||||
|
||||
// Helper: Lookup value in route path
|
||||
export const getAttr = (r, path) => {
|
||||
@ -85,18 +91,32 @@ export const ColAsPath = ({route}) => {
|
||||
if(!asns){
|
||||
asns = [];
|
||||
}
|
||||
const baseUrl = "https://irrexplorer.nlnog.net/asn/AS"
|
||||
let asnLinks = asns.map((asn, i) => {
|
||||
return (<a key={`${asn}_${i}`} href={baseUrl + asn} target="_blank" rel="noreferrer">{asn} </a>);
|
||||
});
|
||||
|
||||
return (
|
||||
<td>
|
||||
{asnLinks}
|
||||
<AsPath asns={asns} />
|
||||
</td>
|
||||
);
|
||||
}
|
||||
|
||||
// ASN
|
||||
export const ColAsn = ({route, column, onClick}) => {
|
||||
const asn = getAttr(route, column);
|
||||
return (
|
||||
<td className="col-route-asn">
|
||||
<AsnLink asn={asn} />
|
||||
</td>
|
||||
);
|
||||
}
|
||||
|
||||
// Route Age
|
||||
export const ColAge = ({route, onClick}) => {
|
||||
return (
|
||||
<td className="route-age">
|
||||
<span onClick={onClick}><RouteAgeRelative route={route} /></span>
|
||||
</td>
|
||||
);
|
||||
}
|
||||
|
||||
export const ColFlags = ({route}) => {
|
||||
return (
|
||||
<td className="col-route-flags">
|
||||
@ -127,9 +147,13 @@ const RouteColumn = ({onClick, column, route}) => {
|
||||
|
||||
"Flags": ColFlags,
|
||||
"ASPath": ColAsPath,
|
||||
"asn": ColAsn,
|
||||
"neighbor.asn": ColAsn,
|
||||
|
||||
"routeserver.name": ColRouteServer,
|
||||
"neighbor.description": ColNeighbor,
|
||||
|
||||
"age": ColAge,
|
||||
};
|
||||
|
||||
let Cell = cells[column] || ColDefault;
|
||||
|
@ -156,6 +156,10 @@ $labelOffsetEnd: -70px;
|
||||
width: 100%;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.route-age {
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user