aboutsummaryrefslogtreecommitdiff
path: root/src/webui.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/webui.rs')
-rw-r--r--src/webui.rs65
1 files changed, 34 insertions, 31 deletions
diff --git a/src/webui.rs b/src/webui.rs
index 9b21ab0..5a66ffc 100644
--- a/src/webui.rs
+++ b/src/webui.rs
@@ -3,7 +3,7 @@ use axum::extract::State as S;
use axum::response::Html;
use markup::doctype;
use serde_json::{Map, Value};
-use std::sync::Arc;
+use std::{collections::HashSet, sync::Arc};
use tokio::{fs::read_to_string, sync::RwLock};
pub(crate) async fn webui_style() -> Css<String> {
@@ -16,6 +16,8 @@ pub(crate) async fn webui_style() -> Css<String> {
pub(crate) async fn webui(S(state): S<Arc<RwLock<State>>>) -> Html<String> {
let g = state.read().await;
+ let default = &Map::new();
+ let g = &g;
let doc = markup::new! {
@doctype()
@@ -33,27 +35,9 @@ pub(crate) async fn webui(S(state): S<Arc<RwLock<State>>>) -> Html<String> {
}}
}
section.tasks {
- div {
- h2 { "Queued" }
- p.count { @g.queue.len() " tasks" }
- ul { @for key in &g.queue {
- li { @Task { key, data: g.metadata.get(key).unwrap(), class: "task queue" } }
- }}
- }
- div {
- h2 { "Loading" }
- p.count { @g.loading.len() " tasks" }
- ul { @for key in &g.loading {
- li { @Task { key, data: g.metadata.get(key).unwrap(), class: "task loading" } }
- }}
- }
- div {
- h2 { "Completed" }
- p.count { @g.complete.len() " tasks" }
- ul { @for key in &g.complete {
- li { @Task { key, data: g.metadata.get(key).unwrap(), class: "task complete" } }
- }}
- }
+ @Taskbin {title: "Queued", class: "task queue", set: &g.queue, default, g }
+ @Taskbin {title: "Loading", class: "task loading", set: &g.loading, default, g }
+ @Taskbin {title: "Completed", class: "task complete", set: &g.complete, default, g }
}
}
}
@@ -62,28 +46,47 @@ pub(crate) async fn webui(S(state): S<Arc<RwLock<State>>>) -> Html<String> {
}
markup::define!(
+ Taskbin<'a>(title: &'a str, class: &'a str, set: &'a HashSet<String>, g: &'a State, default: &'a Map<String, Value>) {
+ div {
+ h2 { @title }
+ p.count { @set.len() " tasks" }
+ ul { @for key in set.iter().take(128) {
+ li { @Task { key, data: g.metadata.get(key).unwrap_or(&default), class } }
+ }}
+ }
+ }
+ Task<'a>(key: &'a str, data: &'a Map<String, Value>, class: &'a str) {
+ div[class=class] {
+ // @if let Some(url) = data.get("thumbnail").and_then(Value::as_str) {
+ // img[src=url, loading="lazy"];
+ // }
+ h3 { @data.get("title").and_then(Value::as_str).unwrap_or(key) }
+ @if let Some(s) = data.get("subtitle").and_then(Value::as_str) {
+ span.subtitle { @s } br;
+ }
+ span.key { @key }
+ }
+ }
Worker<'a>(id: u64, w: &'a crate::Worker) {
div[class=worker_class(w)] {
h3 { @w.name }
- span { "ID: " @id } " "
- @if w.accept > 0 {
- span { "Accepting Jobs (" @w.accept ")" }
+ span { "ID: " @id } ", "
+ @if !w.assigned_tasks.is_empty() {
+ span { "Busy (" @w.assigned_tasks.len() ")" }
+ } else if w.accept > 0 {
+ span { "Accepting Tasks (" @w.accept ")" }
} else {
span { "Idle" }
}
}
}
- Task<'a>(key: &'a str, data: &'a Map<String, Value>, class: &'a str) {
- div[class=class] {
- h3 { @data["title"].as_str().unwrap_or(key) }
- span.key { @key }
- }
- }
);
fn worker_class(w: &crate::Worker) -> &'static str {
if w.accept > 0 {
"worker accepting"
+ } else if w.assigned_tasks.is_empty() {
+ "worker idle"
} else {
"worker busy"
}