1
0
Fork 0
mirror of https://github.com/Nutomic/ibis.git synced 2024-11-22 09:01:09 +00:00

also resolve articles/instances on search page

This commit is contained in:
Felix Ableitner 2024-02-01 12:52:55 +01:00
parent 1dc984025a
commit 862297638f
4 changed files with 50 additions and 25 deletions

View file

@ -216,15 +216,9 @@ pub(in crate::backend::api) async fn fork_article(
pub(super) async fn resolve_article(
Query(query): Query<ResolveObject>,
data: Data<MyDataHandle>,
) -> MyResult<Json<ArticleView>> {
let article: DbArticle = ObjectId::from(query.id).dereference(&data).await?;
let edits = DbEdit::read_for_article(&article, &data.db_connection)?;
let latest_version = edits.last().unwrap().hash.clone();
Ok(Json(ArticleView {
article,
edits,
latest_version,
}))
) -> MyResult<Json<DbArticle>> {
let article = ObjectId::from(query.id).dereference(&data).await?;
Ok(Json(article))
}
/// Search articles for matching title or body text.

View file

@ -42,7 +42,6 @@ pub(super) async fn resolve_instance(
Query(query): Query<ResolveObject>,
data: Data<MyDataHandle>,
) -> MyResult<Json<DbInstance>> {
// TODO: workaround because axum makes it hard to have multiple routes on /
let instance: DbInstance = ObjectId::from(query.id).dereference(&data).await?;
Ok(Json(instance))
}

View file

@ -156,7 +156,7 @@ impl ApiClient {
Ok(handle_json_res(req).await.unwrap())
}
pub async fn resolve_article(&self, id: Url) -> MyResult<ArticleView> {
pub async fn resolve_article(&self, id: Url) -> MyResult<DbArticle> {
let resolve_object = ResolveObject { id };
self.get_query("article/resolve", Some(resolve_object))
.await

View file

@ -1,34 +1,66 @@
use crate::common::SearchArticleData;
use crate::common::{DbArticle, DbInstance, SearchArticleData};
use crate::frontend::app::GlobalState;
use futures::join;
use leptos::*;
use leptos_router::use_query_map;
use serde::{Deserialize, Serialize};
use url::Url;
#[derive(Default, Clone, Deserialize, Serialize)]
struct SearchResults {
articles: Vec<DbArticle>,
instance: Option<DbInstance>,
}
#[component]
pub fn Search() -> impl IntoView {
let params = use_query_map();
let query = params.get_untracked().get("query").cloned().unwrap();
let query_ = query.clone();
let search_results = create_resource(
move || query_.clone(),
move |query| async move {
GlobalState::api_client()
.search(&SearchArticleData { query })
.await
.unwrap()
},
);
let query = move || params.get().get("query").cloned().unwrap();
let search_results = create_resource(query, move |query| async move {
let mut search_results = SearchResults::default();
let api_client = GlobalState::api_client();
let url = Url::parse(&query);
let search_data = SearchArticleData { query };
let search = api_client.search(&search_data);
// If its a valid url, also attempt to resolve as federation object
if let Ok(url) = url {
let resolve_article = api_client.resolve_article(url.clone());
let resolve_instance = api_client.resolve_instance(url);
let (search, resolve_article, resolve_instance) =
join!(search, resolve_article, resolve_instance);
search_results.instance = resolve_instance.ok();
if let Ok(article) = resolve_article {
search_results.articles.push(article);
}
search_results.articles.append(&mut search.unwrap())
} else {
search_results.articles.append(&mut search.await.unwrap())
}
search_results
});
view! {
<h1>"Search results for "{query}</h1>
<Suspense fallback=|| view! { "Loading..." }> {
move || search_results.get().map(|search_results| {
let is_empty = search_results.is_empty();
let is_empty = search_results.articles.is_empty() && search_results.instance.is_none();
view! {
<Show when=move || !is_empty
fallback=|| view! { <p>No results found</p> }>
<ul>
{
search_results
// render resolved instance
if let Some(instance) = &search_results.instance {
let ap_id = instance.ap_id.to_string();
vec![view! { <li>
<a href={format!("/instance/{ap_id}")}>{ap_id}</a>
</li>}]
} else { vec![] }
}
{
// render articles from resolve/search
search_results.articles
.iter()
.map(|a| view! { <li>
<a href={format!("/article/{}", a.title)}>{a.title()}</a>