break search out into own module
This commit is contained in:
parent
61ad0a17e8
commit
8ee362b991
6 changed files with 84 additions and 62 deletions
|
@ -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<axum::Router> {
|
|||
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 = {
|
||||
|
|
70
src/search.rs
Normal file
70
src/search.rs
Normal file
|
@ -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<Watch>,
|
||||
pub user: Option<User>,
|
||||
}
|
||||
|
||||
#[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<String>,
|
||||
#[serde(default, deserialize_with = "empty_string_as_none")]
|
||||
pub title: Option<String>,
|
||||
#[serde(default, deserialize_with = "empty_string_as_none")]
|
||||
pub kind: Option<String>,
|
||||
#[serde(default, deserialize_with = "empty_string_as_none")]
|
||||
pub year: Option<i64>,
|
||||
}
|
||||
|
||||
pub async fn get_search_watch(
|
||||
auth: AuthSession,
|
||||
State(pool): State<SqlitePool>,
|
||||
search: Query<SearchQuery>,
|
||||
) -> 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<Watch> = query.fetch_all(&pool).await.unwrap();
|
||||
|
||||
SearchPage {
|
||||
results: watches,
|
||||
user,
|
||||
}
|
||||
}
|
|
@ -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<String>,
|
||||
#[serde(default, deserialize_with = "empty_string_as_none")]
|
||||
pub title: Option<String>,
|
||||
#[serde(default, deserialize_with = "empty_string_as_none")]
|
||||
pub kind: Option<String>,
|
||||
#[serde(default, deserialize_with = "empty_string_as_none")]
|
||||
pub year: Option<i64>,
|
||||
}
|
||||
|
||||
// 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<SqlitePool>) -> i
|
|||
MyWatchesPage { watches, user }
|
||||
}
|
||||
|
||||
pub async fn get_search_watch(
|
||||
auth: AuthSession,
|
||||
State(pool): State<SqlitePool>,
|
||||
search: Query<SearchQuery>,
|
||||
) -> 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<Watch> = query.fetch_all(&pool).await.unwrap();
|
||||
|
||||
SearchWatchesPage { watches, user }
|
||||
}
|
||||
|
||||
pub async fn get_watch_status(
|
||||
auth: AuthSession,
|
||||
State(pool): State<SqlitePool>,
|
||||
|
|
|
@ -11,13 +11,6 @@ pub struct MyWatchesPage {
|
|||
pub user: Option<User>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Template, Deserialize, Serialize, PartialEq, Eq, OptionalOptionalUser)]
|
||||
#[template(path = "search_watches_page.html")]
|
||||
pub struct SearchWatchesPage {
|
||||
pub watches: Vec<Watch>,
|
||||
pub user: Option<User>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Template, Deserialize, Serialize, PartialEq, Eq, OptionalOptionalUser)]
|
||||
#[template(path = "get_watch_page.html")]
|
||||
pub struct GetWatchPage {
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for watch in watches %}
|
||||
{% for res in results %}
|
||||
{% include "watch-search-result.html" %}
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
<tr id="watchlist-item-{{watch.id}}">
|
||||
<td><span class="watchtitle"><a href="/watch/{{watch.id}}">{{watch.title}}</a></span></td>
|
||||
<tr id="watchlist-item-{{res.id}}">
|
||||
<td><span class="watchtitle"><a href="/watch/{{res.id}}">{{res.title}}</a></span></td>
|
||||
<td><span>
|
||||
{% match watch.metadata_url %}
|
||||
{% match res.metadata_url %}
|
||||
{% when Some with (mdurl) %}
|
||||
<a href="{{ mdurl }}">{{ mdurl }}</a>
|
||||
{% when None %}
|
||||
{% endmatch %}
|
||||
</span>
|
||||
</td>
|
||||
<td>{{watch.kind}}</td>
|
||||
<td> {% call m::get_or_default(watch.year(), "when??") -%}</td>
|
||||
<td>{{res.kind}}</td>
|
||||
<td> {% call m::get_or_default(res.year(), "when??") -%}</td>
|
||||
<td>
|
||||
<span id="add-watch-{{watch.id}}">
|
||||
<span hx-get="/watch/status/{{watch.id}}" hx-target="this" hx-trigger="load, reveal"
|
||||
<span id="add-watch-{{res.id}}">
|
||||
<span hx-get="/watch/status/{{res.id}}" hx-target="this" hx-trigger="load, reveal"
|
||||
hx-swap="outerHTML">???</span>
|
||||
</span>
|
||||
</td>
|
||||
|
|
Loading…
Reference in a new issue