mirror of
https://github.com/Nutomic/ibis.git
synced 2024-11-22 09:01:09 +00:00
Dont allow empty search queries, error handling for search
This commit is contained in:
parent
05d260d463
commit
575ef14a23
3 changed files with 41 additions and 18 deletions
|
@ -235,6 +235,9 @@ pub(super) async fn search_article(
|
||||||
Query(query): Query<SearchArticleData>,
|
Query(query): Query<SearchArticleData>,
|
||||||
data: Data<IbisData>,
|
data: Data<IbisData>,
|
||||||
) -> MyResult<Json<Vec<DbArticle>>> {
|
) -> MyResult<Json<Vec<DbArticle>>> {
|
||||||
|
if query.query.is_empty() {
|
||||||
|
return Err(anyhow!("Query is empty").into());
|
||||||
|
}
|
||||||
let article = DbArticle::search(&query.query, &data.db_connection)?;
|
let article = DbArticle::search(&query.query, &data.db_connection)?;
|
||||||
Ok(Json(article))
|
Ok(Json(article))
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,8 +18,8 @@ pub fn Nav() -> impl IntoView {
|
||||||
GlobalState::api_client()
|
GlobalState::api_client()
|
||||||
.get_local_instance()
|
.get_local_instance()
|
||||||
.await
|
.await
|
||||||
.unwrap()
|
.map(|i| i.registration_open)
|
||||||
.registration_open
|
.unwrap_or_default()
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -43,7 +43,9 @@ pub fn Nav() -> impl IntoView {
|
||||||
ev.prevent_default();
|
ev.prevent_default();
|
||||||
let navigate = leptos_router::use_navigate();
|
let navigate = leptos_router::use_navigate();
|
||||||
let query = search_query.get();
|
let query = search_query.get();
|
||||||
navigate(&format!("/search?query={query}"), Default::default());
|
if !query.is_empty() {
|
||||||
|
navigate(&format!("/search?query={query}"), Default::default());
|
||||||
|
}
|
||||||
}>
|
}>
|
||||||
<input type="text" placeholder="Search"
|
<input type="text" placeholder="Search"
|
||||||
prop:value=search_query
|
prop:value=search_query
|
||||||
|
|
|
@ -1,42 +1,51 @@
|
||||||
use crate::common::{DbArticle, DbInstance, SearchArticleData};
|
use crate::common::{DbArticle, DbInstance, SearchArticleData};
|
||||||
use crate::frontend::app::GlobalState;
|
use crate::frontend::app::GlobalState;
|
||||||
use crate::frontend::{article_link, article_title};
|
use crate::frontend::{article_link, article_title};
|
||||||
use futures::join;
|
|
||||||
use leptos::*;
|
use leptos::*;
|
||||||
use leptos_router::use_query_map;
|
use leptos_router::use_query_map;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
#[derive(Default, Clone, Deserialize, Serialize)]
|
#[derive(Default, Clone, Deserialize, Serialize, Debug)]
|
||||||
struct SearchResults {
|
struct SearchResults {
|
||||||
articles: Vec<DbArticle>,
|
articles: Vec<DbArticle>,
|
||||||
instance: Option<DbInstance>,
|
instance: Option<DbInstance>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl SearchResults {
|
||||||
|
pub fn is_empty(&self) -> bool {
|
||||||
|
self.articles.is_empty() && self.instance.is_none()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
pub fn Search() -> impl IntoView {
|
pub fn Search() -> impl IntoView {
|
||||||
let params = use_query_map();
|
let params = use_query_map();
|
||||||
let query = move || params.get().get("query").cloned().unwrap();
|
let query = move || params.get().get("query").cloned().unwrap();
|
||||||
|
let (error, set_error) = create_signal(None::<String>);
|
||||||
let search_results = create_resource(query, move |query| async move {
|
let search_results = create_resource(query, move |query| async move {
|
||||||
|
set_error.set(None);
|
||||||
let mut search_results = SearchResults::default();
|
let mut search_results = SearchResults::default();
|
||||||
let api_client = GlobalState::api_client();
|
let api_client = GlobalState::api_client();
|
||||||
let url = Url::parse(&query);
|
let url = Url::parse(&query);
|
||||||
let search_data = SearchArticleData { query };
|
let search_data = SearchArticleData { query };
|
||||||
let search = api_client.search(&search_data);
|
let search = api_client.search(&search_data);
|
||||||
|
|
||||||
|
match search.await {
|
||||||
|
Ok(mut a) => search_results.articles.append(&mut a),
|
||||||
|
Err(e) => set_error.set(Some(e.0.to_string())),
|
||||||
|
}
|
||||||
|
|
||||||
// If its a valid url, also attempt to resolve as federation object
|
// If its a valid url, also attempt to resolve as federation object
|
||||||
if let Ok(url) = url {
|
if let Ok(url) = url {
|
||||||
let resolve_article = api_client.resolve_article(url.clone());
|
match api_client.resolve_article(url.clone()).await {
|
||||||
let resolve_instance = api_client.resolve_instance(url);
|
Ok(a) => search_results.articles.push(a.article),
|
||||||
let (search, resolve_article, resolve_instance) =
|
Err(e) => set_error.set(Some(e.0.to_string())),
|
||||||
join!(search, resolve_article, resolve_instance);
|
}
|
||||||
search_results.instance = resolve_instance.ok();
|
match api_client.resolve_instance(url).await {
|
||||||
if let Ok(article) = resolve_article {
|
Ok(a) => search_results.instance = Some(a),
|
||||||
search_results.articles.push(article.article);
|
Err(e) => set_error.set(Some(e.0.to_string())),
|
||||||
}
|
}
|
||||||
search_results.articles.append(&mut search.unwrap())
|
|
||||||
} else {
|
|
||||||
search_results.articles.append(&mut search.await.unwrap())
|
|
||||||
}
|
}
|
||||||
search_results
|
search_results
|
||||||
});
|
});
|
||||||
|
@ -44,11 +53,20 @@ pub fn Search() -> impl IntoView {
|
||||||
view! {
|
view! {
|
||||||
<h1>"Search results for "{query}</h1>
|
<h1>"Search results for "{query}</h1>
|
||||||
<Suspense fallback=|| view! { "Loading..." }> {
|
<Suspense fallback=|| view! { "Loading..." }> {
|
||||||
move || search_results.get().map(|search_results| {
|
move || search_results.get().map(move |search_results| {
|
||||||
let is_empty = search_results.articles.is_empty() && search_results.instance.is_none();
|
let is_empty = search_results.is_empty();
|
||||||
view! {
|
view! {
|
||||||
<Show when=move || !is_empty
|
<Show when=move || !is_empty
|
||||||
fallback=|| view! { <p>No results found</p> }>
|
fallback=move || {
|
||||||
|
let error_view = move || {
|
||||||
|
error.get().map(|err| {
|
||||||
|
view! { <p style="color:red;">{err}</p> }
|
||||||
|
})
|
||||||
|
};
|
||||||
|
view! {
|
||||||
|
{error_view}
|
||||||
|
<p>No results found</p>
|
||||||
|
}}>
|
||||||
<ul>
|
<ul>
|
||||||
{
|
{
|
||||||
// render resolved instance
|
// render resolved instance
|
||||||
|
|
Loading…
Reference in a new issue