From 56c3a61d8378644f0d3bd2467acc129e46b4f408 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Renault?= Date: Mon, 19 Oct 2020 19:57:15 +0200 Subject: [PATCH] Introduce a new updates page --- public/script.js | 2 +- public/updates-script.js | 37 +++++++++++++++++++ src/subcommand/serve.rs | 80 ++++++++++++++++++++++++++-------------- templates/index.html | 1 + templates/updates.html | 48 ++++++++++++++++++++++++ 5 files changed, 139 insertions(+), 29 deletions(-) create mode 100644 public/updates-script.js create mode 100644 templates/updates.html diff --git a/public/script.js b/public/script.js index 6825c4d9b..4b68d9835 100644 --- a/public/script.js +++ b/public/script.js @@ -51,7 +51,7 @@ $('#search').on('input', function () { } elem.appendChild(ol); - results.appendChild(elem) + results.appendChild(elem); } }, diff --git a/public/updates-script.js b/public/updates-script.js new file mode 100644 index 000000000..f2f68e920 --- /dev/null +++ b/public/updates-script.js @@ -0,0 +1,37 @@ +$(window).on('load', function () { + let url = 'ws://' + window.location.hostname + ':' + window.location.port + '/updates/ws'; + var socket = new WebSocket(url); + + socket.onmessage = function (event) { + console.log(event.data); + + if (event.data.endsWith("processed")) { + const elem = document.createElement('li'); + elem.classList.add("document"); + + const ol = document.createElement('ol'); + const field = document.createElement('li'); + field.classList.add("field"); + + const attribute = document.createElement('div'); + attribute.classList.add("attribute"); + attribute.innerHTML = "TEXT"; + + const content = document.createElement('div'); + content.classList.add("content"); + content.innerHTML = event.data; + + field.appendChild(attribute); + field.appendChild(content); + + ol.appendChild(field); + elem.appendChild(ol); + + prependChild(results, elem); + } + } +}); + +function prependChild(parent, newFirstChild) { + parent.insertBefore(newFirstChild, parent.firstChild) +} diff --git a/src/subcommand/serve.rs b/src/subcommand/serve.rs index 7dbfbd8c2..93f37b5cf 100644 --- a/src/subcommand/serve.rs +++ b/src/subcommand/serve.rs @@ -81,6 +81,13 @@ struct IndexTemplate { docs_count: usize, } +#[derive(Template)] +#[template(path = "updates.html")] +struct UpdatesTemplate { + db_name: String, + updates: Vec, +} + pub fn run(opt: Opt) -> anyhow::Result<()> { stderrlog::new() .verbosity(opt.verbose) @@ -108,10 +115,10 @@ pub fn run(opt: Opt) -> anyhow::Result<()> { let update_store = UpdateStore::open( update_store_options, update_store_path, - move |_uid, meta: String, _content| { - let _ = update_status_sender_cloned.try_send("processing update"); + move |uid, meta: String, _content| { + let _ = update_status_sender_cloned.try_send(format!("processing update {}", uid)); std::thread::sleep(Duration::from_secs(3)); - let _ = update_status_sender_cloned.try_send("update processed"); + let _ = update_status_sender_cloned.try_send(format!("update {} processed", uid)); Ok(meta) })?; @@ -127,9 +134,38 @@ pub fn run(opt: Opt) -> anyhow::Result<()> { // We run and wait on the HTTP server // Expose an HTML page to debug the search in a browser + let db_name_cloned = db_name.clone(); let dash_html_route = warp::filters::method::get() .and(warp::filters::path::end()) - .map(move || IndexTemplate { db_name: db_name.clone(), db_size, docs_count }); + .map(move || IndexTemplate { db_name: db_name_cloned.clone(), db_size, docs_count }); + + let update_store_cloned = update_store.clone(); + let updates_list_or_html_route = warp::filters::method::get() + .and(warp::header("Accept")) + .and(warp::path!("updates")) + .map(move |header: String| { + let update_store = update_store_cloned.clone(); + let mut updates = update_store.iter_metas(|processed, pending| { + let mut updates = Vec::new(); + for result in processed { + let (id, _) = result?; + updates.push(format!("update {} processed", id.get())); + } + for result in pending { + let (id, _) = result?; + updates.push(format!("update {} pending", id.get())); + } + Ok(updates) + }).unwrap(); + + if header.contains("text/html") { + updates.reverse(); + let template = UpdatesTemplate { db_name: db_name.clone(), updates }; + Box::new(template) as Box + } else { + Box::new(warp::reply::json(&updates)) + } + }); let dash_bulma_route = warp::filters::method::get() .and(warp::path!("bulma.min.css")) @@ -180,6 +216,13 @@ pub fn run(opt: Opt) -> anyhow::Result<()> { .body(include_str!("../../public/script.js")) ); + let updates_script_route = warp::filters::method::get() + .and(warp::path!("updates-script.js")) + .map(|| Response::builder() + .header("content-type", "application/javascript; charset=utf-8") + .body(include_str!("../../public/updates-script.js")) + ); + let dash_logo_white_route = warp::filters::method::get() .and(warp::path!("logo-white.svg")) .map(|| Response::builder() @@ -245,7 +288,7 @@ pub fn run(opt: Opt) -> anyhow::Result<()> { async fn buf_stream( update_store: Arc>, - update_status_sender: async_channel::Sender<&'static str>, + update_status_sender: async_channel::Sender, mut stream: impl futures::Stream> + Unpin, ) -> Result { @@ -262,7 +305,7 @@ pub fn run(opt: Opt) -> anyhow::Result<()> { let meta = String::from("I am the metadata"); let uid = update_store.register_update(&meta, &mmap[..]).unwrap(); - update_status_sender.try_send("registering update").unwrap(); + update_status_sender.try_send(format!("update {} pending", uid)).unwrap(); eprintln!("Registering update {}", uid); Ok(warp::reply()) @@ -294,27 +337,8 @@ pub fn run(opt: Opt) -> anyhow::Result<()> { }) }); - let update_store_cloned = update_store.clone(); - let list_updates_route = warp::filters::method::get() - .and(warp::path!("updates")) - .map(move || { - let update_store = update_store_cloned.clone(); - let updates = update_store.iter_metas(|processed, pending| { - let mut updates = Vec::new(); - for result in processed { - let (id, _) = result?; - updates.push(format!("update {} processed", id.get())); - } - for result in pending { - let (id, _) = result?; - updates.push(format!("update {} pending", id.get())); - } - Ok(updates) - }).unwrap(); - Ok(warp::reply::json(&updates)) - }); - let routes = dash_html_route + .or(updates_list_or_html_route) .or(dash_bulma_route) .or(dash_bulma_dark_route) .or(dash_style_route) @@ -322,12 +346,12 @@ pub fn run(opt: Opt) -> anyhow::Result<()> { .or(dash_papaparse_route) .or(dash_filesize_route) .or(dash_script_route) + .or(updates_script_route) .or(dash_logo_white_route) .or(dash_logo_black_route) .or(query_route) .or(indexing_route) - .or(update_ws_route) - .or(list_updates_route); + .or(update_ws_route); let addr = SocketAddr::from_str(&opt.http_listen_addr)?; tokio::runtime::Builder::new() diff --git a/templates/index.html b/templates/index.html index 0cb717c92..0fe6034ea 100644 --- a/templates/index.html +++ b/templates/index.html @@ -89,6 +89,7 @@ + diff --git a/templates/updates.html b/templates/updates.html new file mode 100644 index 000000000..ec83af4e0 --- /dev/null +++ b/templates/updates.html @@ -0,0 +1,48 @@ + + + + + + + + + + {{ db_name }} | Updates + + + +
+
+
+ +
+
+ milli logo in white + milli logo in black +
+
+
+
+
+ +
+
    + + {% for update in updates %} +
  1. +
      +
    1. +
      text
      {{ update }}
      +
    2. +
    +
  2. + {% endfor %} + +
+
+ + + + + +