From 8ee362b991de0fe20b6a72ed3f861cf16d7e4e4d Mon Sep 17 00:00:00 2001 From: Joe Ardent Date: Fri, 9 Feb 2024 16:56:05 -0800 Subject: [PATCH] break search out into own module --- src/lib.rs | 6 ++- src/search.rs | 70 ++++++++++++++++++++++++++++++ src/watches/handlers.rs | 47 +------------------- src/watches/templates.rs | 7 --- templates/search_watches_page.html | 2 +- templates/watch-search-result.html | 14 +++--- 6 files changed, 84 insertions(+), 62 deletions(-) create mode 100644 src/search.rs diff --git a/src/lib.rs b/src/lib.rs index 0f4ba95..17ef676 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -29,6 +29,7 @@ mod auth; mod db; mod generic_handlers; mod login; +mod search; mod signup; mod stars; mod templates; @@ -47,11 +48,12 @@ pub async fn app(db_pool: sqlx::SqlitePool) -> IntoMakeService { use auth::*; use generic_handlers::{handle_slash, handle_slash_redir}; use login::{get_login, get_logout, post_login, post_logout}; + use search::get_search_watch; use signup::handlers::{get_create_user, get_signup_success, post_create_user}; use tower_http::services::ServeDir; use watches::handlers::{ - get_add_new_watch, get_search_watch, get_watch, get_watch_status, get_watches, - post_add_new_watch, post_add_watch_quest, + get_add_new_watch, get_watch, get_watch_status, get_watches, post_add_new_watch, + post_add_watch_quest, }; let auth_layer = { diff --git a/src/search.rs b/src/search.rs new file mode 100644 index 0000000..d8d4555 --- /dev/null +++ b/src/search.rs @@ -0,0 +1,70 @@ +use askama::Template; +use axum::{ + extract::{Query, State}, + response::IntoResponse, +}; +use serde::{Deserialize, Serialize}; +use sqlx::{query_as, SqlitePool}; + +use crate::{ + misc_util::empty_string_as_none, AuthSession, OptionalOptionalUser, Star, User, Watch, +}; + +#[derive(Debug, Default, Template, Deserialize, Serialize, PartialEq, Eq, OptionalOptionalUser)] +#[template(path = "search_watches_page.html")] +pub struct SearchPage { + pub results: Vec, + pub user: Option, +} + +#[derive(Debug, Clone, Deserialize, PartialEq, Eq)] +pub enum SearchResult { + Star(Star), + Watch(Watch), +} + +#[derive(Debug, Default, Clone, Deserialize, PartialEq, Eq)] +pub struct SearchQuery { + #[serde(default, deserialize_with = "empty_string_as_none")] + pub search: Option, + #[serde(default, deserialize_with = "empty_string_as_none")] + pub title: Option, + #[serde(default, deserialize_with = "empty_string_as_none")] + pub kind: Option, + #[serde(default, deserialize_with = "empty_string_as_none")] + pub year: Option, +} + +pub async fn get_search_watch( + auth: AuthSession, + State(pool): State, + search: Query, +) -> impl IntoResponse { + const DEFAULT_WATCHES_QUERY: &str = + "select * from (select * from watches order by random() limit 50) order by release_date asc"; + + let user = auth.user; + let search_query = search.0; + + let query = if search_query == SearchQuery::default() { + query_as(DEFAULT_WATCHES_QUERY) + } else if let Some(title) = search_query.title { + query_as( + "select * from watches where id in (select id from watch_search where title match ? order by rank)", + ) + .bind(title) + } else if let Some(ref search) = search_query.search { + query_as("select * from watches where id in (select id from watch_search where title match ?) outer join (select * from stars where id in (select id from star_search where name match ?)) s") + .bind(search).bind(search) + } else { + query_as(DEFAULT_WATCHES_QUERY) + }; + + // until tantivy search + let watches: Vec = query.fetch_all(&pool).await.unwrap(); + + SearchPage { + results: watches, + user, + } +} diff --git a/src/watches/handlers.rs b/src/watches/handlers.rs index fac2c5b..6bcf0c7 100644 --- a/src/watches/handlers.rs +++ b/src/watches/handlers.rs @@ -1,5 +1,5 @@ use axum::{ - extract::{Form, Path, Query, State}, + extract::{Form, Path, State}, http::StatusCode, response::{IntoResponse, Redirect, Response}, }; @@ -8,7 +8,7 @@ use julid::Julid; use serde::Deserialize; use sqlx::{query, query_as, query_scalar, SqlitePool}; -use super::templates::{AddNewWatchPage, AddWatchButton, GetWatchPage, SearchWatchesPage}; +use super::templates::{AddNewWatchPage, AddWatchButton, GetWatchPage}; use crate::{ misc_util::{empty_string_as_none, year_to_epoch}, AuthSession, MyWatchesPage, ShowKind, Watch, WatchQuest, @@ -23,9 +23,6 @@ const GET_QUEST_QUERY: &str = "select * from watch_quests where user = ? and wat const GET_WATCH_QUERY: &str = "select * from watches where id = $1"; -const DEFAULT_WATCHES_QUERY: &str = - "select * from (select * from watches order by random() limit 50) order by release_date asc"; - const ADD_WATCH_QUERY: &str = "insert into watches (title, kind, release_date, metadata_url, added_by, length) values ($1, $2, $3, $4, $5, $6) returning id"; const ADD_WATCH_QUEST_QUERY: &str = "insert into watch_quests (user, watch, public, watched) values ($1, $2, $3, $4)"; @@ -65,18 +62,6 @@ impl IntoResponse for AddError { // Types for receiving arguments from forms //-************************************************************************ -#[derive(Debug, Default, Clone, Deserialize, PartialEq, Eq)] -pub struct SearchQuery { - #[serde(default, deserialize_with = "empty_string_as_none")] - pub search: Option, - #[serde(default, deserialize_with = "empty_string_as_none")] - pub title: Option, - #[serde(default, deserialize_with = "empty_string_as_none")] - pub kind: Option, - #[serde(default, deserialize_with = "empty_string_as_none")] - pub year: Option, -} - // kinda the main form? #[derive(Debug, Default, Deserialize, PartialEq, Eq)] pub struct PostAddNewWatch { @@ -239,34 +224,6 @@ pub async fn get_watches(auth: AuthSession, State(pool): State) -> i MyWatchesPage { watches, user } } -pub async fn get_search_watch( - auth: AuthSession, - State(pool): State, - search: Query, -) -> impl IntoResponse { - let user = auth.user; - let search_query = search.0; - - let query = if search_query == SearchQuery::default() { - query_as(DEFAULT_WATCHES_QUERY) - } else if let Some(title) = search_query.title { - query_as( - "select * from watches where id in (select id from watch_search where title match ? order by rank)", - ) - .bind(title) - } else if let Some(ref search) = search_query.search { - query_as("select * from watches where id in (select id from watch_search where title match ?) outer join (select * from stars where id in (select id from star_search where name match ?)) s") - .bind(search).bind(search) - } else { - query_as(DEFAULT_WATCHES_QUERY) - }; - - // until tantivy search - let watches: Vec = query.fetch_all(&pool).await.unwrap(); - - SearchWatchesPage { watches, user } -} - pub async fn get_watch_status( auth: AuthSession, State(pool): State, diff --git a/src/watches/templates.rs b/src/watches/templates.rs index 89159d8..fb058ae 100644 --- a/src/watches/templates.rs +++ b/src/watches/templates.rs @@ -11,13 +11,6 @@ pub struct MyWatchesPage { pub user: Option, } -#[derive(Debug, Default, Template, Deserialize, Serialize, PartialEq, Eq, OptionalOptionalUser)] -#[template(path = "search_watches_page.html")] -pub struct SearchWatchesPage { - pub watches: Vec, - pub user: Option, -} - #[derive(Debug, Default, Template, Deserialize, Serialize, PartialEq, Eq, OptionalOptionalUser)] #[template(path = "get_watch_page.html")] pub struct GetWatchPage { diff --git a/templates/search_watches_page.html b/templates/search_watches_page.html index 0c1e62c..f87f31a 100644 --- a/templates/search_watches_page.html +++ b/templates/search_watches_page.html @@ -18,7 +18,7 @@ - {% for watch in watches %} + {% for res in results %} {% include "watch-search-result.html" %} {% endfor %} diff --git a/templates/watch-search-result.html b/templates/watch-search-result.html index 8614876..cdf8369 100644 --- a/templates/watch-search-result.html +++ b/templates/watch-search-result.html @@ -1,18 +1,18 @@ - - {{watch.title}} + + {{res.title}} - {% match watch.metadata_url %} + {% match res.metadata_url %} {% when Some with (mdurl) %} {{ mdurl }} {% when None %} {% endmatch %} - {{watch.kind}} - {% call m::get_or_default(watch.year(), "when??") -%} + {{res.kind}} + {% call m::get_or_default(res.year(), "when??") -%} - - + ???