summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorToby Vincent <tobyv@tobyvin.dev>2024-10-13 20:44:03 -0500
committerToby Vincent <tobyv@tobyvin.dev>2024-10-13 20:44:03 -0500
commitd3768b1d9712436da6df4e1eef54737890035f62 (patch)
tree11f9dfb2595b0d19f7811d13ceff6ef076b7d5ec
parentaac6390f82d1f8626c466b531870dc5bde080f87 (diff)
feat: improve ui and add test service
-rw-r--r--assets/index.css108
-rw-r--r--assets/index.html1
-rw-r--r--assets/index.js58
-rw-r--r--config.toml6
-rw-r--r--favicon.svg2
-rw-r--r--src/service.rs17
6 files changed, 146 insertions, 46 deletions
diff --git a/assets/index.css b/assets/index.css
index dff7a03..9d6fca2 100644
--- a/assets/index.css
+++ b/assets/index.css
@@ -1,3 +1,68 @@
+:root {
+ color-scheme: light dark;
+ --bg: #1d2021;
+ --bg-hard: #282828;
+ --bg1: #3c3836;
+ --bg2: #504945;
+ --bg3: #665c54;
+ --bg4: #7c6f64;
+ --fg: #f9f5d7;
+ --fg-hard: #fdf4c1;
+ --fg1: #ebdbb2;
+ --fg2: #d5c4a1;
+ --fg3: #bdae93;
+ --fg4: #a89984;
+ --red: #cc2412;
+ --green: #98971a;
+ --yellow: #d79921;
+ --blue: #458588;
+ --purple: #b16286;
+ --cyan: #689d6a;
+ --gray: #a89984;
+ --orange: #d65d0e;
+ --bright-red: #fb4934;
+ --bright-green: #b8bb26;
+ --bright-yellow: #fabd2f;
+ --bright-blue: #83a598;
+ --bright-purple: #d3869b;
+ --bright-cyan: #8ec07c;
+ --bright-gray: #928374;
+ --bright-orange: #fe8019;
+}
+
+@media (prefers-color-scheme: light) {
+ :root {
+ --bg: #f9f5d7;
+ --bg-hard: #fdf4c1;
+ --bg1: #ebdbb2;
+ --bg2: #d5c4a1;
+ --bg3: #bdae93;
+ --bg4: #a89984;
+ --fg: #1d2021;
+ --fg-hard: #282828;
+ --fg1: #3c3836;
+ --fg2: #504945;
+ --fg3: #665c54;
+ --fg4: #7c6f64;
+ --red: #9d0006;
+ --green: #79740e;
+ --yellow: #b57614;
+ --blue: #076678;
+ --purple: #8f3f71;
+ --cyan: #427b58;
+ --orange: #af3a03;
+ --gray: #928374;
+ --bright-red: #cc2412;
+ --bright-green: #98971a;
+ --bright-yellow: #d79921;
+ --bright-blue: #458598;
+ --bright-purple: #b16286;
+ --bright-cyan: #689d6a;
+ --bright-orange: #d65d0e;
+ --bright-gray: #7c6f64;
+ }
+}
+
html {
background: var(--bg);
color: var(--fg);
@@ -11,7 +76,6 @@ body {
width: calc(100vw - 4rem);
max-width: 640px;
margin: 0 2rem 1rem;
- line-height: 1.4;
align-self: center;
}
main {
@@ -21,14 +85,19 @@ main {
hgroup {
text-align: center;
}
+hr {
+ border-width: 0;
+}
table {
width: 100%;
max-width: 500px;
align-self: center;
border-collapse: collapse;
+ background: var(--bg1);
+ color: var(--fg1);
}
-tr {
- border: 2px solid #ddd;
+tbody {
+ border: 2px solid var(--bg4);
}
td {
padding: 5px;
@@ -37,32 +106,29 @@ td {
td:first-of-type + td {
text-align: right;
}
-td > details > summary {
- text-align: right;
-}
-td > details {
- text-align: left;
+tr:first-of-type + tr {
+ border-top: 1px solid var(--bg3);
}
+
.ok {
- color: #228b22;
+ color: var(--bright-green);
}
.warning {
- color: #ff8c00;
+ color: var(--bright-yellow);
}
.error {
- color: #dc143c;
+ color: var(--bright-red);
}
-#status {
- color: #fff;
- background: #228b22;
-}
-#status.ok {
- background: #228b22;
+.details {
+ visibility: collapse;
+ font-size: 8pt;
+ color: var(--fg-hard);
+ background: var(--bg-hard);
}
-#status.warning {
- background: #ff8c00;
+:hover + .details {
+ visibility: visible;
}
-#status.error {
- background: #dc143c;
+:hover {
+ visibility: visible;
}
diff --git a/assets/index.html b/assets/index.html
index c03a7b7..dfa316a 100644
--- a/assets/index.html
+++ b/assets/index.html
@@ -3,6 +3,7 @@
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
+ <link rel="icon" type="image/svg" href="/favicon.svg" />
<link rel="stylesheet" type="text/css" href="index.css" />
<script src="index.js"></script>
</head>
diff --git a/assets/index.js b/assets/index.js
index 12bce67..a4e5c2b 100644
--- a/assets/index.js
+++ b/assets/index.js
@@ -1,4 +1,5 @@
const serviceMap = new Map();
+const elementMap = new Map();
async function getServices() {
const url = "api/v1/list";
@@ -28,35 +29,44 @@ function updateStatus() {
}
}
-function updateService(statusElm, name, data) {
+function createStatusTbody(name, data) {
+ const tbody = document.createElement("tbody");
+
+ const trowService = document.createElement("tr");
+ const tdataName = document.createElement("td");
+ tdataName.textContent = name;
+ trowService.appendChild(tdataName);
+
+ const tdataStatus = document.createElement("td");
switch (data.status) {
case "ok": {
- statusElm.innerHTML = "";
- statusElm.textContent = "Ok";
- statusElm.setAttribute("class", "ok");
+ tdataStatus.textContent = "Ok";
+ tdataStatus.setAttribute("class", "ok");
serviceMap.set(name, true);
break;
}
case "error": {
- const summaryElm = document.createElement("summary");
- summaryElm.textContent = "Error";
-
- const expandElm = document.createElement("code");
- expandElm.textContent = data.output;
-
- const detailsElm = document.createElement("details");
- detailsElm.appendChild(summaryElm);
- detailsElm.appendChild(expandElm);
-
- statusElm.innerHTML = "";
- statusElm.appendChild(detailsElm);
- statusElm.setAttribute("class", "error");
+ tdataStatus.textContent = "Error";
+ tdataStatus.setAttribute("class", "error");
serviceMap.set(name, false);
break;
}
}
- updateStatus();
+ trowService.appendChild(tdataStatus);
+ tbody.appendChild(trowService);
+
+ if (data.output) {
+ const trowOutput = document.createElement("tr");
+ trowOutput.setAttribute("class", "details");
+ const tdataOutput = document.createElement("td");
+ tdataOutput.textContent = data.output;
+ tdataOutput.setAttribute("colspan", "2");
+ trowOutput.appendChild(tdataOutput);
+ tbody.appendChild(trowOutput);
+ }
+
+ return tbody;
}
getServices().then((services) => {
@@ -67,15 +77,15 @@ getServices().then((services) => {
for (const service of services) {
const table = document.getElementById("services");
- const row = table.insertRow();
- const nameElm = row.insertCell();
- nameElm.textContent = service;
- const statusElm = row.insertCell();
+ let tbody = createStatusTbody(service, { "data": "ok" });
+ table.appendChild(tbody);
evtSource.addEventListener(service, (event) => {
data = JSON.parse(event.data);
- updateService(statusElm, service, data);
- console.log(`service: ${service}, event: ${event}`);
+ tbodyNew = createStatusTbody(service, data);
+ tbody.replaceWith(tbodyNew);
+ tbody = tbodyNew;
+ updateStatus();
});
}
});
diff --git a/config.toml b/config.toml
index e91e94f..8084a90 100644
--- a/config.toml
+++ b/config.toml
@@ -7,12 +7,16 @@ kind = "http"
url = "https://tobyvin.dev"
[[services]]
-name = "test_cmd"
+name = "stat"
kind = "exec"
command = "stat"
args = ["/tmp/test_file"]
[[services]]
+name = "test"
+kind = "test"
+
+[[services]]
name = "dns"
kind = "tcp"
address = "10.42.0.1:53"
diff --git a/favicon.svg b/favicon.svg
new file mode 100644
index 0000000..2a8e2b3
--- /dev/null
+++ b/favicon.svg
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
+<svg fill="#000000" width="800px" height="800px" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg"><path d="M320.2 243.8l-49.7 99.4c-6 12.1-23.4 11.7-28.9-.6l-56.9-126.3-30 71.7H60.6l182.5 186.5c7.1 7.3 18.6 7.3 25.7 0L451.4 288H342.3l-22.1-44.2zM473.7 73.9l-2.4-2.5c-51.5-52.6-135.8-52.6-187.4 0L256 100l-27.9-28.5c-51.5-52.7-135.9-52.7-187.4 0l-2.4 2.4C-10.4 123.7-12.5 203 31 256h102.4l35.9-86.2c5.4-12.9 23.6-13.2 29.4-.4l58.2 129.3 49-97.9c5.9-11.8 22.7-11.8 28.6 0l27.6 55.2H481c43.5-53 41.4-132.3-7.3-182.1z"/></svg> \ No newline at end of file
diff --git a/src/service.rs b/src/service.rs
index b67ba51..74ecb1d 100644
--- a/src/service.rs
+++ b/src/service.rs
@@ -13,6 +13,21 @@ pub trait IntoService {
) -> impl std::future::Future<Output = ()>;
}
+impl IntoService for () {
+ async fn into_service(self, tx: tokio::sync::watch::Sender<Status>) {
+ let mut interval = tokio::time::interval(std::time::Duration::from_secs(3));
+ let mut status = Status::Ok;
+
+ loop {
+ interval.tick().await;
+ status = match tx.send_replace(status) {
+ Status::Ok => Status::Error(Some("Test status is in the error state".into())),
+ Status::Error(_) => Status::Ok,
+ };
+ }
+ }
+}
+
pub fn default_interval() -> std::time::Duration {
std::time::Duration::from_secs(5)
}
@@ -31,11 +46,13 @@ pub enum ServiceKind {
Http(http::Http),
Tcp(tcp::Tcp),
Exec(command::Command),
+ Test(()),
}
impl IntoService for ServiceKind {
async fn into_service(self, tx: tokio::sync::watch::Sender<Status>) {
match self {
+ ServiceKind::Test(()) => ().into_service(tx).await,
ServiceKind::Http(h) => h.into_service(tx).await,
ServiceKind::Tcp(t) => t.into_service(tx).await,
ServiceKind::Exec(c) => c.into_service(tx).await,