285 lines
10 KiB
Rust
285 lines
10 KiB
Rust
use maud::{html, Markup, PreEscaped};
|
|
use peach_lib::sbot::{SbotConfig, SbotStatus};
|
|
|
|
use crate::{
|
|
templates,
|
|
utils::{sbot, theme},
|
|
};
|
|
|
|
// HTML RENDERING FOR ELEMENTS
|
|
|
|
// TODO: refactor this to make better use of splices
|
|
// https://maud.lambda.xyz/splices-toggles.html
|
|
|
|
fn downtime_element(downtime: &Option<String>) -> Markup {
|
|
match downtime {
|
|
Some(time) => {
|
|
html! {
|
|
label class="label-small font-gray" for="sbotDowntime" title="go-sbot downtime" style="margin-top: 0.5rem;" { "DOWNTIME" }
|
|
p id="sbotDowntime" class="card-text" title="Downtime" { (time) }
|
|
}
|
|
}
|
|
_ => html! { (PreEscaped("")) },
|
|
}
|
|
}
|
|
|
|
fn uptime_element(uptime: &Option<String>) -> Markup {
|
|
match uptime {
|
|
Some(time) => {
|
|
html! {
|
|
label class="label-small font-gray" for="sbotUptime" title="go-sbot uptime" style="margin-top: 0.5rem;" { "UPTIME" }
|
|
p id="sbotUptime" class="card-text" title="Uptime" { (time) }
|
|
}
|
|
}
|
|
_ => html! { (PreEscaped("")) },
|
|
}
|
|
}
|
|
|
|
fn run_on_startup_element(boot_state: &Option<String>) -> Markup {
|
|
match boot_state {
|
|
Some(state) if state == "enabled" => {
|
|
html! {
|
|
p id="runOnStartup" class="card-text" title="Enabled" { "Enabled" }
|
|
}
|
|
}
|
|
_ => {
|
|
html! {
|
|
p id="runOnStartup" class="card-text" title="Disabled" { "Disabled" }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
fn database_element(state: &str) -> Markup {
|
|
// retrieve the sequence number of the latest message in the sbot database
|
|
let sequence_num = sbot::latest_sequence_number();
|
|
|
|
match (state, sequence_num) {
|
|
// if the state is "active" and latest_sequence_number() was successful
|
|
("active", Ok(number)) => {
|
|
html! {
|
|
label class="card-text" style="margin-right: 5px;" { (number) }
|
|
label class="label-small font-gray" { "MESSAGES IN LOCAL DATABASE" }
|
|
}
|
|
}
|
|
(_, _) => html! { label class="label-small font-gray" { "DATABASE UNAVAILABLE" } },
|
|
}
|
|
}
|
|
|
|
fn memory_element(memory: Option<u32>) -> Markup {
|
|
let (memory, img_class, medium_label_class, small_label_class) = match memory {
|
|
Some(mem) => {
|
|
// convert memory to mb representation
|
|
let memory_rounded = mem / 1024 / 1024;
|
|
(
|
|
memory_rounded.to_string(),
|
|
"icon icon-active",
|
|
"label-medium font-normal",
|
|
"label-small font-gray",
|
|
)
|
|
}
|
|
_ => (
|
|
0.to_string(),
|
|
"icon icon-inactive",
|
|
"label-medium font-gray",
|
|
"label-small font-gray",
|
|
),
|
|
};
|
|
|
|
html! {
|
|
div class="stack" {
|
|
img class=(img_class) title="Memory" src="/icons/ram.png";
|
|
div class="flex-grid" style="padding-top: 0.5rem;" {
|
|
label class=(medium_label_class) style="padding-right: 3px;" title="Memory usage of the go-sbot process in MB" { (memory) }
|
|
label class=(small_label_class) { "MB" }
|
|
}
|
|
label class=(small_label_class) { "MEMORY" }
|
|
}
|
|
}
|
|
}
|
|
|
|
fn hops_element() -> Markup {
|
|
// retrieve go-sbot systemd process status
|
|
let hops = match SbotConfig::read() {
|
|
Ok(conf) => conf.hops,
|
|
_ => 0,
|
|
};
|
|
|
|
html! {
|
|
div class="stack" {
|
|
img class="icon icon-active" title="Hops" src="/icons/orbits.png";
|
|
div class="flex-grid" style="padding-top: 0.5rem;" {
|
|
label class="label-medium font-normal" style="padding-right: 3px;" title="Replication hops" {
|
|
(hops)
|
|
}
|
|
}
|
|
label class="label-small font-gray" { "HOPS" }
|
|
}
|
|
}
|
|
}
|
|
|
|
fn blobs_element(blobstore: Option<u64>) -> Markup {
|
|
let blobstore_size = match blobstore {
|
|
// convert blobstore size to mb representation
|
|
Some(blobs) => blobs / 1024 / 1024,
|
|
None => 0,
|
|
};
|
|
|
|
html! {
|
|
div class="stack" {
|
|
img class="icon icon-active" title="Blobs" src="/icons/image-file.png";
|
|
div class="flex-grid" style="padding-top: 0.5rem;" {
|
|
label class="label-medium font-normal" style="padding-right: 3px;" title="Blobstore size in MB" { (blobstore_size) }
|
|
label class="label-small font-normal" { "MB" }
|
|
}
|
|
label class="label-small font-gray" { "BLOBSTORE" }
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Read the state of the go-sbot process and define status-related
|
|
/// elements accordingly.
|
|
fn render_status_elements<'a>() -> (
|
|
String,
|
|
&'a str,
|
|
&'a str,
|
|
Markup,
|
|
Markup,
|
|
Markup,
|
|
Markup,
|
|
Markup,
|
|
) {
|
|
// retrieve go-sbot systemd process status
|
|
match SbotStatus::read() {
|
|
Ok(status) if status.state == Some("active".to_string()) => (
|
|
"ACTIVE".to_string(),
|
|
"capsule capsule-container border-success",
|
|
"center icon icon-active",
|
|
uptime_element(&status.uptime),
|
|
run_on_startup_element(&status.boot_state),
|
|
database_element("active"),
|
|
memory_element(status.memory),
|
|
blobs_element(status.blobstore),
|
|
),
|
|
Ok(status) if status.state == Some("inactive".to_string()) => (
|
|
"INACTIVE".to_string(),
|
|
"capsule capsule-container border-warning",
|
|
"center icon icon-inactive",
|
|
downtime_element(&status.downtime),
|
|
run_on_startup_element(&status.boot_state),
|
|
database_element("inactive"),
|
|
memory_element(None),
|
|
blobs_element(status.blobstore),
|
|
),
|
|
// state is neither active nor inactive (might be "failed")
|
|
Ok(status) if status.state.is_some() => (
|
|
status.state.unwrap().to_uppercase(),
|
|
"capsule capsule-container border-danger",
|
|
"center icon icon-inactive",
|
|
downtime_element(&None),
|
|
run_on_startup_element(&status.boot_state),
|
|
database_element("failed"),
|
|
memory_element(None),
|
|
blobs_element(status.blobstore),
|
|
),
|
|
Ok(status) if status.state.is_none() => (
|
|
"UNAVAILABLE".to_string(),
|
|
"capsule capsule-container border-danger",
|
|
"center icon icon-inactive",
|
|
downtime_element(&None),
|
|
run_on_startup_element(&status.boot_state),
|
|
database_element("unavailable"),
|
|
memory_element(None),
|
|
blobs_element(status.blobstore),
|
|
),
|
|
_ => (
|
|
"PROCESS QUERY FAILED".to_string(),
|
|
"capsule capsule-container border-danger",
|
|
"center icon icon-inactive",
|
|
downtime_element(&None),
|
|
run_on_startup_element(&None),
|
|
database_element("error"),
|
|
memory_element(None),
|
|
blobs_element(None),
|
|
),
|
|
}
|
|
}
|
|
|
|
/// Scuttlebutt status template builder.
|
|
pub fn build_template() -> PreEscaped<String> {
|
|
let (
|
|
sbot_state,
|
|
capsule_class,
|
|
sbot_icon_class,
|
|
uptime_downtime_element,
|
|
run_on_startup_element,
|
|
database_element,
|
|
memory_element,
|
|
blobs_element,
|
|
) = render_status_elements();
|
|
|
|
let hops_element = hops_element();
|
|
|
|
let status_template = html! {
|
|
(PreEscaped("<!-- SCUTTLEBUTT STATUS -->"))
|
|
div class="card center" {
|
|
(PreEscaped("<!-- SBOT INFO BOX -->"))
|
|
div class=(capsule_class) {
|
|
(PreEscaped("<!-- SBOT STATUS GRID -->"))
|
|
div class="two-grid" title="go-sbot process state" {
|
|
(PreEscaped("<!-- top-right config icon -->"))
|
|
a class="link two-grid-top-right" href="/settings/scuttlebutt" title="Configure Scuttlebutt settings" {
|
|
img id="configureNetworking" class="icon-small icon-active" src="/icons/cog.svg" alt="Configure";
|
|
}
|
|
(PreEscaped("<!-- left column -->"))
|
|
(PreEscaped("<!-- go-sbot state icon with label -->"))
|
|
div class="grid-column-1" {
|
|
img id="sbotStateIcon" class=(sbot_icon_class) src="/icons/hermies.svg" alt="Hermies";
|
|
label id="sbotStateLabel" for="sbotStateIcon" class="center label-small font-gray" style="margin-top: 0.5rem;" title="Sbot state" {
|
|
(sbot_state)
|
|
}
|
|
}
|
|
(PreEscaped("<!-- right column -->"))
|
|
(PreEscaped("<!-- go-sbot version and uptime / downtime with labels -->"))
|
|
div class="grid-column-2" {
|
|
label class="label-small font-gray" for="sbotVersion" title="go-sbot version" {
|
|
"VERSION"
|
|
}
|
|
p id="sbotVersion" class="card-text" title="Version" {
|
|
"1.1.0-alpha"
|
|
}
|
|
(uptime_downtime_element)
|
|
label class="label-small font-gray" for="sbotBootState" title="go-sbot boot state" style="margin-top: 0.5rem;" { "RUN ON STARTUP" }
|
|
(run_on_startup_element)
|
|
}
|
|
}
|
|
hr style="color: var(--light-gray);";
|
|
div id="middleSection" style="margin-top: 1rem;" {
|
|
div id="sbotInfo" class="center" style="display: flex; justify-content: space-between; width: 90%;" {
|
|
div class="center" style="display: flex; align-items: last baseline;" {
|
|
(database_element)
|
|
}
|
|
}
|
|
}
|
|
hr style="color: var(--light-gray);";
|
|
(PreEscaped("<!-- THREE-ACROSS STACK -->"))
|
|
div class="three-grid card-container" style="margin-top: 1rem;" {
|
|
(hops_element)
|
|
(blobs_element)
|
|
(memory_element)
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
// wrap the nav bars around the scuttlebutt status card template content
|
|
// parameters are template, title and back url
|
|
let body = templates::nav::build_template(status_template, "Status", Some("/"));
|
|
|
|
// query the current theme so we can pass it into the base template builder
|
|
let theme = theme::get_theme();
|
|
|
|
// render the base template with the provided body
|
|
templates::base::build_template(body, theme)
|
|
}
|