diff --git a/src/html/page/block.rs b/src/html/page/block.rs index fefe41a..5147842 100644 --- a/src/html/page/block.rs +++ b/src/html/page/block.rs @@ -1,7 +1,8 @@ use crate::html::component::header::HeaderHtml; +use crate::html::page::not_found::not_found_html_response; use crate::model::app_state::AppState; use crate::model::path_block_selector::PathBlockSelector; -use crate::rpc::block_info::block_info_with_value_worker; +use axum::extract::rejection::PathRejection; use axum::extract::Path; use axum::extract::State; use axum::response::Html; @@ -10,18 +11,22 @@ use html_escaper::Escape; use html_escaper::Trusted; use neptune_core::rpc_server::BlockInfo; use std::sync::Arc; +use tarpc::context; pub async fn block_page( - Path(path_block_selector): Path, + user_input_maybe: Result, PathRejection>, state: State>, ) -> Result, Response> { + let Path(path_block_selector) = user_input_maybe + .map_err(|e| not_found_html_response(state.clone(), Some(e.to_string())))?; + let value_path: Path<(PathBlockSelector, String)> = Path((path_block_selector, "".to_string())); - block_page_with_value(value_path, state).await + block_page_with_value(Ok(value_path), state).await } #[axum::debug_handler] pub async fn block_page_with_value( - Path((path_block_selector, value)): Path<(PathBlockSelector, String)>, + user_input_maybe: Result, PathRejection>, State(state): State>, ) -> Result, Response> { #[derive(boilerplate::Boilerplate)] @@ -31,12 +36,32 @@ pub async fn block_page_with_value( block_info: BlockInfo, } + let Path((path_block_selector, value)) = user_input_maybe + .map_err(|e| not_found_html_response(State(state.clone()), Some(e.to_string())))?; + let header = HeaderHtml { site_name: "Neptune Explorer".to_string(), state: state.clone(), }; - let block_info = block_info_with_value_worker(state, path_block_selector, &value).await?; + let block_selector = path_block_selector + .as_block_selector(&value) + .map_err(|e| not_found_html_response(State(state.clone()), Some(e.to_string())))?; + + let block_info = match state + .clone() + .rpc_client + .block_info(context::current(), block_selector) + .await + .map_err(|e| not_found_html_response(State(state.clone()), Some(e.to_string())))? + { + Some(info) => Ok(info), + None => Err(not_found_html_response( + State(state), + Some("Block does not exist".to_string()), + )), + }?; + let block_info_page = BlockInfoHtmlPage { header, block_info }; Ok(Html(block_info_page.to_string())) } diff --git a/src/html/page/mod.rs b/src/html/page/mod.rs index a705c02..765ec18 100644 --- a/src/html/page/mod.rs +++ b/src/html/page/mod.rs @@ -1,3 +1,4 @@ pub mod block; +pub mod not_found; pub mod root; pub mod utxo; diff --git a/src/html/page/utxo.rs b/src/html/page/utxo.rs index 7a25926..8096f7d 100644 --- a/src/html/page/utxo.rs +++ b/src/html/page/utxo.rs @@ -1,7 +1,7 @@ use crate::html::component::header::HeaderHtml; -use crate::http_util::not_found_err; -use crate::http_util::rpc_err; +use crate::html::page::not_found::not_found_html_response; use crate::model::app_state::AppState; +use axum::extract::rejection::PathRejection; use axum::extract::Path; use axum::extract::State; use axum::response::Html; @@ -14,7 +14,7 @@ use tarpc::context; #[axum::debug_handler] pub async fn utxo_page( - Path(index): Path, + index_maybe: Result, PathRejection>, State(state): State>, ) -> Result, Response> { #[derive(boilerplate::Boilerplate)] @@ -25,14 +25,22 @@ pub async fn utxo_page( digest: Digest, } + let Path(index) = index_maybe + .map_err(|e| not_found_html_response(State(state.clone()), Some(e.to_string())))?; + let digest = match state .rpc_client .utxo_digest(context::current(), index) .await - .map_err(rpc_err)? + .map_err(|e| not_found_html_response(State(state.clone()), Some(e.to_string())))? { Some(digest) => digest, - None => return Err(not_found_err()), + None => { + return Err(not_found_html_response( + State(state.clone()), + Some("The requested UTXO does not exist".to_string()), + )) + } }; let header = HeaderHtml { diff --git a/src/http_util.rs b/src/http_util.rs index 975ba3e..2a7efc8 100644 --- a/src/http_util.rs +++ b/src/http_util.rs @@ -1,4 +1,5 @@ use axum::http::StatusCode; +use axum::response::Html; use axum::response::IntoResponse; use axum::response::Response; use tarpc::client::RpcError; @@ -10,6 +11,10 @@ pub fn not_found_err() -> Response { (StatusCode::NOT_FOUND, "Not Found".to_string()).into_response() } +pub fn not_found_html_err(html: Html) -> Response { + (StatusCode::NOT_FOUND, html).into_response() +} + pub fn rpc_err(e: RpcError) -> Response { (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()).into_response() } diff --git a/src/main.rs b/src/main.rs index bdf6028..e341ddd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -58,6 +58,13 @@ async fn main() -> Result<(), RpcError> { .route("/block/:selector/:value", get(block_page_with_value)) .route("/utxo/:value", get(utxo_page)) // -- Static files -- + .route_service( + "/css/pico.min.css", + ServeFile::new(concat!( + env!("CARGO_MANIFEST_DIR"), + "/templates/web/css/pico.min.css" + )), + ) .route_service( "/css/styles.css", ServeFile::new(concat!( diff --git a/templates/web/css/styles.css b/templates/web/css/styles.css index f15e33f..230f57f 100644 --- a/templates/web/css/styles.css +++ b/templates/web/css/styles.css @@ -1,42 +1,8 @@ -div.box h1, -div.box h2, -div.box h3 { - margin-top: 0px; - margin-bottom: 5px; -} - div.indent { position: relative; left: 20px; } -div.box { - margin-bottom: 10px; - border: solid 1px #ccc; - border-top-left-radius: 15px; - padding: 10px; -} - -body { - font-family: arial, helvetica; -} - -table.alt { - margin-top: 10px; - margin-bottom: 10px; - padding: 10px; - border-collapse: collapse; -} - -table.alt td, -th { - padding: 5px; -} - -table.alt tr:nth-child(odd) td { - background: #eee; -} - -table.alt tr:nth-child(even) td { - background: #fff; +.center-text { + text-align: center; } diff --git a/templates/web/html/components/header.html b/templates/web/html/components/header.html index 145b929..6b4087e 100644 --- a/templates/web/html/components/header.html +++ b/templates/web/html/components/header.html @@ -1 +1,3 @@ -

{{self.site_name}} : {{self.state.network}}

\ No newline at end of file +
+

{{self.site_name}} : {{self.state.network}}

+
\ No newline at end of file diff --git a/templates/web/html/page/block_info.html b/templates/web/html/page/block_info.html index dd92c13..2ae5dec 100644 --- a/templates/web/html/page/block_info.html +++ b/templates/web/html/page/block_info.html @@ -1,13 +1,19 @@ + Neptune Block Explorer: Block Height {{self.block_info.height}} + + {{Trusted(self.header.to_string())}} +
+ +

Block height: {{self.block_info.height}}

@@ -18,7 +24,7 @@

This is the Latest Block (tip)

%% } - +
@@ -53,6 +59,10 @@
Digest {{self.block_info.digest.to_hex()}}
+
+ + +
\ No newline at end of file diff --git a/templates/web/html/page/not_found.html b/templates/web/html/page/not_found.html new file mode 100644 index 0000000..82617a7 --- /dev/null +++ b/templates/web/html/page/not_found.html @@ -0,0 +1,37 @@ + + + + Neptune Block Explorer: Not Found + + + + + + + +
+ +
+

Not found

+
+These are not the droids you're looking for. +
+ +%% if self.error_msg.len() > 0 { +
+Hint: {{self.error_msg}} +
+%% } +
+ + + +
+ + \ No newline at end of file diff --git a/templates/web/html/page/root.html b/templates/web/html/page/root.html index 848bbcc..216b033 100644 --- a/templates/web/html/page/root.html +++ b/templates/web/html/page/root.html @@ -2,28 +2,36 @@ Neptune Block Explorer: (network: {{self.network}}) - - -

Neptune Block Explorer (network: {{self.network}})

+ + -
-

Block Lookup

+ + +
+

Neptune Block Explorer (network: {{self.network}})

+
+ +
+ +
+
+Block Lookup
Block height or digest: @@ -33,58 +41,70 @@ Block height or digest: Quick Lookup: Genesis Block | Tip
-
+ + - -
-

Utxo Lookup

+
+
+Utxo Lookup Utxo index: -
+ +

REST RPCs

- + + - + + -
- -

/utxo_digest

+ -
+ diff --git a/templates/web/html/page/utxo.html b/templates/web/html/page/utxo.html index 5189ed8..fcf6930 100644 --- a/templates/web/html/page/utxo.html +++ b/templates/web/html/page/utxo.html @@ -2,14 +2,19 @@ Neptune Block Explorer: Utxo {{self.index}} + + {{Trusted(self.header.to_string())}} -

Utxo Information

- +
+ +
+Utxo Information +
@@ -19,12 +24,16 @@
Index {{self.index}}{{self.digest.to_hex()}}
+ + + \ No newline at end of file