diff options
Diffstat (limited to 'server/src/routes/ui/search.rs')
-rw-r--r-- | server/src/routes/ui/search.rs | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/server/src/routes/ui/search.rs b/server/src/routes/ui/search.rs new file mode 100644 index 0000000..dc90df1 --- /dev/null +++ b/server/src/routes/ui/search.rs @@ -0,0 +1,74 @@ +use super::{ + account::session::Session, + error::MyResult, + layout::{DynLayoutPage, LayoutPage}, + node::NodeCard, +}; +use edit_distance::edit_distance; +use jellybase::database::{DataAcid, ReadableTable, T_NODE, T_USER_NODE}; +use rocket::{get, State}; + +#[get("/search?<query>")] +pub async fn r_search<'a>( + session: Session, + db: &State<DataAcid>, + query: Option<&str>, +) -> MyResult<DynLayoutPage<'a>> { + let results = if let Some(query) = query { + let mut items = { + let txn = db.begin_read()?; + let nodes = txn.open_table(T_NODE)?; + let node_users = txn.open_table(T_USER_NODE)?; + let i = nodes + .iter()? + .map(|a| { + let (x, y) = a.unwrap(); + let (x, y) = (x.value().to_owned(), y.value().0); + let z = node_users + .get(&(session.user.name.as_str(), x.as_str())) + .unwrap() + .map(|z| z.value().0) + .unwrap_or_default(); + let y = y.public; + (x, y, z) + }) + .collect::<Vec<_>>(); + drop(nodes); + i + }; + + let query = query.to_lowercase(); + items.sort_by_cached_key(|(_, n, _)| { + n.title + .as_ref() + .map(|x| x.to_lowercase()) + .unwrap_or_default() + .split(" ") + .map(|tok| edit_distance(query.as_str(), tok)) + .min() + .unwrap_or(usize::MAX) + }); + + Some(items.into_iter().take(64).collect::<Vec<_>>()) + } else { + None + }; + + Ok(LayoutPage { + title: "Search".to_string(), + class: None, + content: markup::new! { + h1 { "Search" } + form[action="", method="GET"] { + input[type="text", name="query"]; + input[type="submit"]; + } + @if let Some(results) = &results { + h2 { "Results" } + ul.children {@for (id, node, udata) in results.iter() { + li { @NodeCard { id, node, udata } } + }} + } + }, + }) +} |