diff options
author | metamuffin <metamuffin@disroot.org> | 2025-04-27 19:25:11 +0200 |
---|---|---|
committer | metamuffin <metamuffin@disroot.org> | 2025-04-27 19:25:11 +0200 |
commit | 11a585b3dbe620dcc8772e713b22f1d9ba80d598 (patch) | |
tree | 44f8d97137412aefc79a2425a489c34fa3e5f6c5 /server/src/ui/search.rs | |
parent | d871aa7c5bba49ff55170b5d2dac9cd440ae7170 (diff) | |
download | jellything-11a585b3dbe620dcc8772e713b22f1d9ba80d598.tar jellything-11a585b3dbe620dcc8772e713b22f1d9ba80d598.tar.bz2 jellything-11a585b3dbe620dcc8772e713b22f1d9ba80d598.tar.zst |
move files around
Diffstat (limited to 'server/src/ui/search.rs')
-rw-r--r-- | server/src/ui/search.rs | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/server/src/ui/search.rs b/server/src/ui/search.rs new file mode 100644 index 0000000..96be3a6 --- /dev/null +++ b/server/src/ui/search.rs @@ -0,0 +1,69 @@ +/* + This file is part of jellything (https://codeberg.org/metamuffin/jellything) + which is licensed under the GNU Affero General Public License (version 3); see /COPYING. + Copyright (C) 2025 metamuffin <metamuffin.org> +*/ +use super::{ + error::MyResult, + layout::{trs, DynLayoutPage, LayoutPage}, + node::{DatabaseNodeUserDataExt, NodeCard}, +}; +use crate::{api::AcceptJson, locale::AcceptLanguage, logic::session::Session}; +use anyhow::anyhow; +use jellybase::{database::Database, locale::tr}; +use jellycommon::{api::ApiSearchResponse, Visibility}; +use rocket::{get, serde::json::Json, Either, State}; +use std::time::Instant; + +#[get("/search?<query>&<page>")] +pub async fn r_search<'a>( + session: Session, + db: &State<Database>, + aj: AcceptJson, + query: Option<&str>, + page: Option<usize>, + lang: AcceptLanguage, +) -> MyResult<Either<DynLayoutPage<'a>, Json<ApiSearchResponse>>> { + let AcceptLanguage(lang) = lang; + let results = if let Some(query) = query { + let timing = Instant::now(); + let (count, ids) = db.search(query, 32, page.unwrap_or_default() * 32)?; + let mut nodes = ids + .into_iter() + .map(|id| db.get_node_with_userdata(id, &session)) + .collect::<Result<Vec<_>, anyhow::Error>>()?; + nodes.retain(|(n, _)| n.visibility >= Visibility::Reduced); + let search_dur = timing.elapsed(); + Some((count, nodes, search_dur)) + } else { + None + }; + let query = query.unwrap_or_default().to_string(); + + Ok(if *aj { + let Some((count, results, _)) = results else { + Err(anyhow!("no query"))? + }; + Either::Right(Json(ApiSearchResponse { count, results })) + } else { + Either::Left(LayoutPage { + title: tr(lang, "search.title").to_string(), + class: Some("search"), + content: markup::new! { + h1 { @trs(&lang, "search.title") } + form[action="", method="GET"] { + input[type="text", name="query", placeholder=&*tr(lang, "search.placeholder"), value=&query]; + input[type="submit", value="Search"]; + } + @if let Some((count, results, search_dur)) = &results { + h2 { @trs(&lang, "search.results.title") } + p.stats { @tr(lang, "search.results.stats").replace("{count}", &count.to_string()).replace("{dur}", &format!("{search_dur:?}")) } + ul.children {@for (node, udata) in results.iter() { + li { @NodeCard { node, udata, lang: &lang } } + }} + // TODO pagination + } + }, + }) + }) +} |