Skip to content
This repository was archived by the owner on Mar 27, 2023. It is now read-only.

Commit cb25c1c

Browse files
author
Michel Zimmer
committed
1 parent e964300 commit cb25c1c

File tree

6 files changed

+79
-5
lines changed

6 files changed

+79
-5
lines changed

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,5 @@ LABEL org.opencontainers.image.vendor="neuland – Büro für Informatik GmbH"
2626
LABEL org.opencontainers.image.licenses="MIT"
2727
LABEL org.opencontainers.image.title="bandwhichd-ui"
2828
LABEL org.opencontainers.image.description="bandwhichd ui displaying network topology and statistics"
29-
LABEL org.opencontainers.image.version="0.6.0"
29+
LABEL org.opencontainers.image.version="0.6.1"
3030
COPY --from=build --chown=root:root /home/node/dist /usr/share/nginx/html

mocks/stats.json

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "bandwhichd-ui",
3-
"version": "0.6.0",
3+
"version": "0.6.1",
44
"description": "bandwhichd ui displaying network topology and statistics",
55
"license": "MIT",
66
"private": true,

src/HostDetails.tsx

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import React, { useState } from "react";
12
import { Map } from "immutable";
23
import { Connection, Host, HostId, Stats, UnmonitoredHost } from "./Stats";
34

@@ -16,6 +17,15 @@ export const HostDetails: React.FC<HostDetailsProps> =
1617
}
1718
const selectedHost = props.maybeSelectedHost;
1819

20+
const osReleasName: string =
21+
selectedHost.os_release === null
22+
? "Unknown"
23+
: selectedHost.os_release.pretty_name !== null
24+
&& selectedHost.os_release.pretty_name.length > 0
25+
? selectedHost.os_release.pretty_name
26+
: `${selectedHost.os_release.id} ${selectedHost.os_release.version_id}`;
27+
const [showOsReleaseDetails, setShowOsReleaseDetails] = useState<boolean>(false);
28+
1929
const connectionsToMonitoredHosts = selectedHost
2030
.connections
2131
.flatMap<HostId, { hostDetails: Host, connectionDetails: Connection }>((connection, hostId) => {
@@ -63,6 +73,32 @@ export const HostDetails: React.FC<HostDetailsProps> =
6373
return <aside className={style["host-details"]}>
6474
<section>
6575
<p>{selectedHost.hostname}</p>
76+
<p>OS: {osReleasName} {selectedHost.os_release && <button onClick={_ => setShowOsReleaseDetails(!showOsReleaseDetails)}>{showOsReleaseDetails ? "-" : "+"}</button>}</p>
77+
{
78+
selectedHost.os_release && showOsReleaseDetails &&
79+
<table>
80+
<tbody>
81+
<tr>
82+
<td>Pretty name:</td>
83+
<td>
84+
<code>{selectedHost.os_release?.pretty_name}</code>
85+
</td>
86+
</tr>
87+
<tr>
88+
<td>Id:</td>
89+
<td>
90+
<code>{selectedHost.os_release?.id}</code>
91+
</td>
92+
</tr>
93+
<tr>
94+
<td>Version id:</td>
95+
<td>
96+
<code>{selectedHost.os_release?.version_id}</code>
97+
</td>
98+
</tr>
99+
</tbody>
100+
</table>
101+
}
66102
</section>
67103
<section>
68104
{
@@ -75,7 +111,7 @@ export const HostDetails: React.FC<HostDetailsProps> =
75111
{
76112
connectionsToMonitoredHosts
77113
.entrySeq()
78-
.sortBy(([_, {hostDetails}]) => hostDetails.hostname)
114+
.sortBy(([_, { hostDetails }]) => hostDetails.hostname)
79115
.map(([hostId, { hostDetails }]) => <li key={hostId}>
80116
{
81117
hostId === selectedHost.hostId
@@ -99,7 +135,7 @@ export const HostDetails: React.FC<HostDetailsProps> =
99135
{
100136
connectionsToUnmonitoredHosts
101137
.entrySeq()
102-
.sortBy(([_, {unmonitoredHostDetails}]) => unmonitoredHostDetails.host)
138+
.sortBy(([_, { unmonitoredHostDetails }]) => unmonitoredHostDetails.host)
103139
.map(([hostId, { unmonitoredHostDetails }]) => <li key={hostId}>{unmonitoredHostDetails.host}</li>)
104140
}
105141
</ul>

src/Stats.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import * as Decoder from "io-ts/lib/Decoder"
33
import { mapDecoder } from "./lib/immutable/io-ts/mapDecoder";
44
import { parseBodyAsJson, rejectNonOk } from "./lib/es/response/promiseUtils";
55
import { decode } from "./lib/io-ts/promiseUtils";
6+
import { undefinedAsNullDecoder } from "./lib/io-ts/undefinedAsNullDecoder";
67

78

89
const hostIdTag = Symbol("HostId");
@@ -15,15 +16,43 @@ export type Hostname = string & { readonly _tag: typeof hostnameTag; };
1516
const createHostname: (value: string) => Hostname = (value) => value as Hostname;
1617
const hostnameDecoder = Decoder.map(createHostname)(Decoder.string);
1718

19+
const osReleaseIdTag = Symbol("OsReleaseId");
20+
export type OsReleaseId = string & { readonly _tag: typeof osReleaseIdTag; };
21+
const createOsReleaseId: (value: string) => OsReleaseId = (value) => value as OsReleaseId;
22+
const osReleaseIdDecoder = Decoder.map(createOsReleaseId)(Decoder.string);
23+
24+
const osReleasePrettyNameTag = Symbol("OsReleasePrettyName");
25+
export type OsReleasePrettyName = string & { readonly _tag: typeof osReleasePrettyNameTag; };
26+
const createOsReleasePrettyName: (value: string) => OsReleasePrettyName = (value) => value as OsReleasePrettyName;
27+
const osReleasePrettyNameDecoder = Decoder.map(createOsReleasePrettyName)(Decoder.string);
28+
29+
const osReleaseVersionIdTag = Symbol("OsReleaseVersionId");
30+
export type OsReleaseVersionId = string & { readonly _tag: typeof osReleaseVersionIdTag; };
31+
const createOsReleaseVersionId: (value: string) => OsReleaseVersionId = (value) => value as OsReleaseVersionId;
32+
const osReleaseVersionIdDecoder = Decoder.map(createOsReleaseVersionId)(Decoder.string);
33+
34+
export interface OsRelease {
35+
readonly id: OsReleaseId | null;
36+
readonly pretty_name: OsReleasePrettyName | null;
37+
readonly version_id: OsReleaseVersionId | null;
38+
}
39+
const osReleaseDecoder = Decoder.struct({
40+
id: undefinedAsNullDecoder(osReleaseIdDecoder),
41+
pretty_name: undefinedAsNullDecoder(osReleasePrettyNameDecoder),
42+
version_id: undefinedAsNullDecoder(osReleaseVersionIdDecoder),
43+
});
44+
1845
export interface Connection { }
1946
const connectionDecoder = Decoder.struct({});
2047

2148
export interface Host {
2249
readonly hostname: Hostname;
50+
readonly os_release: OsRelease | null;
2351
readonly connections: Map<HostId, Connection>;
2452
}
2553
const hostDecoder = Decoder.struct({
2654
hostname: hostnameDecoder,
55+
os_release: undefinedAsNullDecoder(osReleaseDecoder),
2756
connections: mapDecoder(hostIdDecoder, connectionDecoder),
2857
});
2958

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import * as Decoder from "io-ts/lib/Decoder";
2+
3+
export const undefinedAsNullDecoder: <A>(decoder: Decoder.Decoder<unknown, A>) => Decoder.Decoder<unknown, A | null> =
4+
<A>(decoder: Decoder.Decoder<unknown, A>) => ({
5+
decode: (i: unknown) =>
6+
i === undefined
7+
? Decoder.success(null)
8+
: decoder.decode(i)
9+
})

0 commit comments

Comments
 (0)