From e0bbf15c6fa6438ada15293e510bc32dae630a3d Mon Sep 17 00:00:00 2001 From: Jeremy Wall Date: Wed, 7 Feb 2024 14:37:24 -0600 Subject: [PATCH] refactor: serve the js libraries via url --- src/main.rs | 1 + src/routes.rs | 46 +++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 42 insertions(+), 5 deletions(-) diff --git a/src/main.rs b/src/main.rs index 483d9a8..35efdb6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -63,6 +63,7 @@ async fn main() -> anyhow::Result<()> { let config = std::sync::Arc::new(dashboard::read_dashboard_list(args.config.as_path())?); let router = Router::new() // JSON api endpoints + .nest("/js", routes::mk_js_routes(config.clone())) .nest("/api", routes::mk_api_routes(config.clone())) // HTMX ui component endpoints .nest("/ui", routes::mk_ui_routes(config.clone())) diff --git a/src/routes.rs b/src/routes.rs index c679430..b577316 100644 --- a/src/routes.rs +++ b/src/routes.rs @@ -15,9 +15,11 @@ use std::sync::Arc; use axum::{ extract::{Path, State}, + response::Response, routing::get, Json, Router, }; +use axum_macros::debug_handler; use maud::{html, Markup, PreEscaped}; use tracing::debug; @@ -61,7 +63,12 @@ pub fn mk_api_routes(config: Arc>) -> Router { // 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); + // 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!( div { h2 { (graph.title) } @@ -89,7 +96,11 @@ pub async fn graph_ui( pub async fn dash_ui(State(config): State, Path(dash_idx): Path) -> 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::>(); + let graph_iter = dash + .graphs + .iter() + .enumerate() + .collect::>(); html!( h1 { (dash.title) } @for (idx, graph) in &graph_iter { @@ -100,7 +111,10 @@ pub async fn dash_ui(State(config): State, Path(dash_idx): Path) pub fn mk_ui_routes(config: Arc>) -> Router { 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( "/dash/:dash_idx/graph/:graph_idx", get(graph_ui).with_state(State(config)), @@ -114,8 +128,8 @@ pub async fn index(State(config): State) -> Markup { title { ("Heracles - Prometheus Unshackled") } } body { - script { (PreEscaped(include_str!("../static/plotly-2.27.0.min.js"))) } - script { (PreEscaped(include_str!("../static/htmx.min.js"))) } + script src="/js/plotly.js" { } + script src="/js/htmx.js" { } (app(State(config.clone())).await) } } @@ -141,3 +155,25 @@ pub async fn app(State(config): State) -> Markup { } } } + +pub fn javascript_response(content: &str) -> Response { + Response::builder() + .header("Content-Type", "text/javascript") + .body(content.to_string()) + .expect("Invalid javascript response") +} + +pub async fn htmx() -> Response { + javascript_response(include_str!("../static/htmx.min.js")) +} + +pub async fn plotly() -> Response { + javascript_response(include_str!("../static/plotly-2.27.0.min.js")) +} + +pub fn mk_js_routes(config: Arc>) -> Router { + Router::new() + .route("/plotly.js", get(plotly)) + .route("/htmx.js", get(htmx)) + .with_state(State(config)) +}