mirror of
https://github.com/zaphar/Heracles.git
synced 2025-07-26 22:09:50 -04:00
Compare commits
No commits in common. "8a6d5d5b9df6c18a31cc4a7cd586348d827f76ca" and "716f2353357e30f1f6ff3b4ab8953aaf77471a34" have entirely different histories.
8a6d5d5b9d
...
716f235335
@ -66,7 +66,7 @@ async fn main() -> anyhow::Result<()> {
|
|||||||
.nest("/api", routes::mk_api_routes(config.clone()))
|
.nest("/api", routes::mk_api_routes(config.clone()))
|
||||||
// HTMX ui component endpoints
|
// HTMX ui component endpoints
|
||||||
.nest("/ui", routes::mk_ui_routes(config.clone()))
|
.nest("/ui", routes::mk_ui_routes(config.clone()))
|
||||||
.route("/", get(routes::index).with_state(State(config.clone())))
|
.route("/", get(routes::index).with_state(config.clone()))
|
||||||
.layer(TraceLayer::new_for_http())
|
.layer(TraceLayer::new_for_http())
|
||||||
.with_state(State(config.clone()));
|
.with_state(State(config.clone()));
|
||||||
let socket_addr = args.listen.unwrap_or("127.0.0.1:3000".to_string());
|
let socket_addr = args.listen.unwrap_or("127.0.0.1:3000".to_string());
|
||||||
|
@ -18,10 +18,10 @@ use axum::{
|
|||||||
routing::get,
|
routing::get,
|
||||||
Json, Router,
|
Json, Router,
|
||||||
};
|
};
|
||||||
use maud::{html, Markup, PreEscaped};
|
use maud::{html, Markup};
|
||||||
use tracing::debug;
|
use tracing::debug;
|
||||||
|
|
||||||
use crate::dashboard::{Dashboard, Graph};
|
use crate::dashboard::Dashboard;
|
||||||
use crate::query::{to_samples, QueryResult};
|
use crate::query::{to_samples, QueryResult};
|
||||||
|
|
||||||
type Config = State<Arc<Vec<Dashboard>>>;
|
type Config = State<Arc<Vec<Dashboard>>>;
|
||||||
@ -58,86 +58,38 @@ pub fn mk_api_routes(config: Arc<Vec<Dashboard>>) -> Router<Config> {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(jwall): This should probably be encapsulated in a web component?
|
|
||||||
pub fn graph_component(dash_idx: usize, graph_idx: usize, graph: &Graph) -> Markup {
|
|
||||||
let graph_id = format!("graph-{}-{}", dash_idx, graph_idx);
|
|
||||||
let script = format!("var data = []; Plotly.newPlot('{}', data, {{ width: 500, height: 500 }});", graph_id);
|
|
||||||
html!(
|
|
||||||
div {
|
|
||||||
h2 { (graph.title) }
|
|
||||||
script {
|
|
||||||
(script)
|
|
||||||
}
|
|
||||||
div id=(graph_id) { }
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn graph_ui(
|
|
||||||
State(config): State<Config>,
|
|
||||||
Path((dash_idx, graph_idx)): Path<(usize, usize)>,
|
|
||||||
) -> Markup {
|
|
||||||
let graph = config
|
|
||||||
.get(dash_idx)
|
|
||||||
.expect("No such dashboard")
|
|
||||||
.graphs
|
|
||||||
.get(graph_idx)
|
|
||||||
.expect("No such graph");
|
|
||||||
graph_component(dash_idx, graph_idx, graph)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn dash_ui(State(config): State<Config>, Path(dash_idx): Path<usize>) -> Markup {
|
|
||||||
// TODO(zaphar): Should do better http error reporting here.
|
|
||||||
let dash = config.get(dash_idx).expect("No such dashboard");
|
|
||||||
let graph_iter = dash.graphs.iter().enumerate().collect::<Vec<(usize, &Graph)>>();
|
|
||||||
html!(
|
|
||||||
h1 { (dash.title) }
|
|
||||||
@for (idx, graph) in &graph_iter {
|
|
||||||
(graph_component(dash_idx, *idx, *graph))
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn mk_ui_routes(config: Arc<Vec<Dashboard>>) -> Router<Config> {
|
pub fn mk_ui_routes(config: Arc<Vec<Dashboard>>) -> Router<Config> {
|
||||||
Router::new()
|
Router::new()
|
||||||
.route("/dash/:dash_idx", get(dash_ui).with_state(State(config.clone())))
|
|
||||||
.route(
|
|
||||||
"/dash/:dash_idx/graph/:graph_idx",
|
|
||||||
get(graph_ui).with_state(State(config)),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn index(State(config): State<Config>) -> Markup {
|
pub async fn index(State(config): Config) -> Markup {
|
||||||
html! {
|
html! {
|
||||||
html {
|
html {
|
||||||
head {
|
head {
|
||||||
title { ("Heracles - Prometheus Unshackled") }
|
title { ("Heracles - Prometheus Unshackled") }
|
||||||
}
|
}
|
||||||
body {
|
body {
|
||||||
script { (PreEscaped(include_str!("../static/plotly-2.27.0.min.js"))) }
|
|
||||||
script { (PreEscaped(include_str!("../static/htmx.min.js"))) }
|
|
||||||
(app(State(config.clone())).await)
|
(app(State(config.clone())).await)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn app(State(config): State<Config>) -> Markup {
|
pub async fn app(State(config): Config) -> Markup {
|
||||||
let titles = config
|
let titles = config
|
||||||
.iter()
|
.iter()
|
||||||
.map(|d| d.title.clone())
|
.map(|d| d.title.clone())
|
||||||
.enumerate()
|
.collect::<Vec<String>>();
|
||||||
.collect::<Vec<(usize, String)>>();
|
|
||||||
html! {
|
html! {
|
||||||
div {
|
div {
|
||||||
// Header menu
|
// Header menu
|
||||||
ul {
|
ul {
|
||||||
@for title in &titles {
|
@for title in &titles {
|
||||||
li hx-get=(format!("/ui/dash/{}", title.0)) hx-target="#dashboard" { (title.1) }
|
li { (title) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// dashboard display
|
// dashboard display
|
||||||
div id="dashboard" { }
|
div { }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
1
static/htmx.min.js
vendored
1
static/htmx.min.js
vendored
File diff suppressed because one or more lines are too long
8
static/plotly-2.27.0.min.js
vendored
8
static/plotly-2.27.0.min.js
vendored
File diff suppressed because one or more lines are too long
Loading…
x
Reference in New Issue
Block a user