rename lol

This commit is contained in:
nora 2022-03-19 14:27:30 +01:00
parent c68cd04af7
commit 543e39f129
70 changed files with 283 additions and 266 deletions

View file

@ -0,0 +1,17 @@
html {
font-family: arial, sans-serif;
background-color: #282c34;
color: white;
}
.app {
margin: 50px;
}
table,
th,
td {
border: 1px solid white;
border-collapse: collapse;
padding: 10px;
}

View file

@ -0,0 +1,20 @@
import React from 'react';
import DataPage from './components/data-page';
import './app.css';
const IS_PROD = process.env.NODE_ENV === 'production';
const URL_PREFIX = IS_PROD ? '' : 'http://localhost:8080/';
const App = () => {
return (
<div className="app">
<header className="header">
<h1>Haesli Dashboard</h1>
</header>
<DataPage prefix={URL_PREFIX} />
</div>
);
};
export default App;

View file

@ -0,0 +1,88 @@
import React, { FC, useCallback, useEffect, useState } from 'react';
import Table from './table';
import type { Data } from '../types';
const fetchData = async (prefix: string): Promise<Data> => {
const url = `${prefix}api/data`;
return fetch(url).then((res) => res.json());
};
type Props = {
prefix: string;
};
const DataPage: FC<Props> = ({ prefix }) => {
const [data, setData] = useState<Data | null>(null);
const refresh = useCallback(async () => {
const newData = await fetchData(prefix);
setData(newData);
}, [setData, prefix]);
useEffect(() => {
const interval = setInterval(refresh, 1000);
return () => clearInterval(interval);
}, [refresh]);
return (
<div>
<section>
<h2>Connections</h2>
{data ? (
<Table
headers={['Connection ID', 'Client Address', 'Channels']}
rows={data.connections.map((connection) => [
connection.id,
connection.peerAddr,
connection.channels.length,
])}
/>
) : (
<div>Loading...</div>
)}
</section>
<section>
<h2>Queues</h2>
{data ? (
<Table
headers={['Queue ID', 'Name', 'Durable', 'Message Count']}
rows={data.queues.map((queue) => [
queue.id,
queue.name,
queue.durable ? 'Yes' : 'No',
queue.messages,
])}
/>
) : (
<div>Loading...</div>
)}
</section>
<section>
<h2>Channels</h2>
{data ? (
<Table
headers={['Channel ID', 'Connection ID', 'Number']}
rows={data.connections
.map((connection) =>
connection.channels.map((channel) => ({
...channel,
connectionId: connection.id,
}))
)
.flat()
.map((channel) => [
channel.id,
channel.connectionId,
channel.number,
])}
/>
) : (
<div>Loading...</div>
)}
</section>
</div>
);
};
export default DataPage;

View file

@ -0,0 +1,31 @@
import React, { FC } from 'react';
type Cell = string | number;
type Row = ReadonlyArray<Cell>;
type Props = {
headers: ReadonlyArray<string>;
rows: ReadonlyArray<Row>;
};
const Table: FC<Props> = ({ headers, rows }) => {
return (
<table>
<tr>
{headers.map((header) => (
<th>{header}</th>
))}
</tr>
{rows.map((row) => (
<tr>
{row.map((cell) => (
<td>{cell}</td>
))}
</tr>
))}
</table>
);
};
export default Table;

View file

@ -0,0 +1,13 @@
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
code {
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
monospace;
}

View file

@ -0,0 +1,11 @@
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './app';
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);

View file

@ -0,0 +1,22 @@
export type Channel = {
id: string;
number: number;
};
export type Connection = {
id: string;
peerAddr: string;
channels: ReadonlyArray<Channel>;
};
export type Queue = {
id: string;
name: string;
durable: boolean;
messages: number;
};
export type Data = {
connections: ReadonlyArray<Connection>;
queues: ReadonlyArray<Queue>;
};