mirror of
https://github.com/zaphar/Heracles.git
synced 2025-07-23 12:39:50 -04:00
refactor: serve the js libraries via url
This commit is contained in:
parent
8a6d5d5b9d
commit
e0bbf15c6f
@ -63,6 +63,7 @@ async fn main() -> anyhow::Result<()> {
|
|||||||
let config = std::sync::Arc::new(dashboard::read_dashboard_list(args.config.as_path())?);
|
let config = std::sync::Arc::new(dashboard::read_dashboard_list(args.config.as_path())?);
|
||||||
let router = Router::new()
|
let router = Router::new()
|
||||||
// JSON api endpoints
|
// JSON api endpoints
|
||||||
|
.nest("/js", routes::mk_js_routes(config.clone()))
|
||||||
.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()))
|
||||||
|
@ -15,9 +15,11 @@ use std::sync::Arc;
|
|||||||
|
|
||||||
use axum::{
|
use axum::{
|
||||||
extract::{Path, State},
|
extract::{Path, State},
|
||||||
|
response::Response,
|
||||||
routing::get,
|
routing::get,
|
||||||
Json, Router,
|
Json, Router,
|
||||||
};
|
};
|
||||||
|
use axum_macros::debug_handler;
|
||||||
use maud::{html, Markup, PreEscaped};
|
use maud::{html, Markup, PreEscaped};
|
||||||
use tracing::debug;
|
use tracing::debug;
|
||||||
|
|
||||||
@ -61,7 +63,12 @@ pub fn mk_api_routes(config: Arc<Vec<Dashboard>>) -> Router<Config> {
|
|||||||
// TODO(jwall): This should probably be encapsulated in a web component?
|
// TODO(jwall): This should probably be encapsulated in a web component?
|
||||||
pub fn graph_component(dash_idx: usize, graph_idx: usize, graph: &Graph) -> Markup {
|
pub fn graph_component(dash_idx: usize, graph_idx: usize, graph: &Graph) -> Markup {
|
||||||
let graph_id = format!("graph-{}-{}", dash_idx, graph_idx);
|
let graph_id = format!("graph-{}-{}", dash_idx, graph_idx);
|
||||||
let script = format!("var data = []; Plotly.newPlot('{}', data, {{ width: 500, height: 500 }});", graph_id);
|
// initialize the plot with Plotly.react
|
||||||
|
// Update plot with Plotly.react which is more efficient
|
||||||
|
let script = format!(
|
||||||
|
"var data = []; Plotly.react('{}', data, {{ width: 500, height: 500 }});",
|
||||||
|
graph_id
|
||||||
|
);
|
||||||
html!(
|
html!(
|
||||||
div {
|
div {
|
||||||
h2 { (graph.title) }
|
h2 { (graph.title) }
|
||||||
@ -89,7 +96,11 @@ pub async fn graph_ui(
|
|||||||
pub async fn dash_ui(State(config): State<Config>, Path(dash_idx): Path<usize>) -> Markup {
|
pub async fn dash_ui(State(config): State<Config>, Path(dash_idx): Path<usize>) -> Markup {
|
||||||
// TODO(zaphar): Should do better http error reporting here.
|
// TODO(zaphar): Should do better http error reporting here.
|
||||||
let dash = config.get(dash_idx).expect("No such dashboard");
|
let dash = config.get(dash_idx).expect("No such dashboard");
|
||||||
let graph_iter = dash.graphs.iter().enumerate().collect::<Vec<(usize, &Graph)>>();
|
let graph_iter = dash
|
||||||
|
.graphs
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.collect::<Vec<(usize, &Graph)>>();
|
||||||
html!(
|
html!(
|
||||||
h1 { (dash.title) }
|
h1 { (dash.title) }
|
||||||
@for (idx, graph) in &graph_iter {
|
@for (idx, graph) in &graph_iter {
|
||||||
@ -100,7 +111,10 @@ pub async fn dash_ui(State(config): State<Config>, Path(dash_idx): Path<usize>)
|
|||||||
|
|
||||||
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",
|
||||||
|
get(dash_ui).with_state(State(config.clone())),
|
||||||
|
)
|
||||||
.route(
|
.route(
|
||||||
"/dash/:dash_idx/graph/:graph_idx",
|
"/dash/:dash_idx/graph/:graph_idx",
|
||||||
get(graph_ui).with_state(State(config)),
|
get(graph_ui).with_state(State(config)),
|
||||||
@ -114,8 +128,8 @@ pub async fn index(State(config): State<Config>) -> Markup {
|
|||||||
title { ("Heracles - Prometheus Unshackled") }
|
title { ("Heracles - Prometheus Unshackled") }
|
||||||
}
|
}
|
||||||
body {
|
body {
|
||||||
script { (PreEscaped(include_str!("../static/plotly-2.27.0.min.js"))) }
|
script src="/js/plotly.js" { }
|
||||||
script { (PreEscaped(include_str!("../static/htmx.min.js"))) }
|
script src="/js/htmx.js" { }
|
||||||
(app(State(config.clone())).await)
|
(app(State(config.clone())).await)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -141,3 +155,25 @@ pub async fn app(State(config): State<Config>) -> Markup {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn javascript_response(content: &str) -> Response<String> {
|
||||||
|
Response::builder()
|
||||||
|
.header("Content-Type", "text/javascript")
|
||||||
|
.body(content.to_string())
|
||||||
|
.expect("Invalid javascript response")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn htmx() -> Response<String> {
|
||||||
|
javascript_response(include_str!("../static/htmx.min.js"))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn plotly() -> Response<String> {
|
||||||
|
javascript_response(include_str!("../static/plotly-2.27.0.min.js"))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn mk_js_routes(config: Arc<Vec<Dashboard>>) -> Router<Config> {
|
||||||
|
Router::new()
|
||||||
|
.route("/plotly.js", get(plotly))
|
||||||
|
.route("/htmx.js", get(htmx))
|
||||||
|
.with_state(State(config))
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user