/* 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 */ use super::{ account::session::Session, error::MyResult, layout::{DynLayoutPage, LayoutPage}, node::{DatabaseNodeUserDataExt, NodeCard}, }; use crate::routes::api::AcceptJson; use anyhow::anyhow; use jellybase::database::Database; use jellycommon::{api::ApiSearchResponse, Visibility}; use rocket::{get, serde::json::Json, Either, State}; use std::time::Instant; #[get("/search?&")] pub async fn r_search<'a>( session: Session, db: &State, aj: AcceptJson, query: Option<&str>, page: Option, ) -> MyResult, Json>> { 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::, 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: "Search".to_string(), class: Some("search"), content: markup::new! { h1 { "Search" } form[action="", method="GET"] { input[type="text", name="query", placeholder="Search Term", value=&query]; input[type="submit", value="Search"]; } @if let Some((count, results, search_dur)) = &results { h2 { "Results" } p.stats { @format!("Found {count} nodes in {search_dur:?}.") } ul.children {@for (node, udata) in results.iter() { li { @NodeCard { node, udata } } }} // TODO pagination } }, }) }) }