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 db;
|
||||||
mod generic_handlers;
|
mod generic_handlers;
|
||||||
mod login;
|
mod login;
|
||||||
|
mod search;
|
||||||
mod signup;
|
mod signup;
|
||||||
mod stars;
|
mod stars;
|
||||||
mod templates;
|
mod templates;
|
||||||
|
@ -47,11 +48,12 @@ pub async fn app(db_pool: sqlx::SqlitePool) -> IntoMakeService<axum::Router> {
|
||||||
use auth::*;
|
use auth::*;
|
||||||
use generic_handlers::{handle_slash, handle_slash_redir};
|
use generic_handlers::{handle_slash, handle_slash_redir};
|
||||||
use login::{get_login, get_logout, post_login, post_logout};
|
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 signup::handlers::{get_create_user, get_signup_success, post_create_user};
|
||||||
use tower_http::services::ServeDir;
|
use tower_http::services::ServeDir;
|
||||||
use watches::handlers::{
|
use watches::handlers::{
|
||||||
get_add_new_watch, get_search_watch, get_watch, get_watch_status, get_watches,
|
get_add_new_watch, get_watch, get_watch_status, get_watches, post_add_new_watch,
|
||||||
post_add_new_watch, post_add_watch_quest,
|
post_add_watch_quest,
|
||||||
};
|
};
|
||||||
|
|
||||||
let auth_layer = {
|
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::{
|
use axum::{
|
||||||
extract::{Form, Path, Query, State},
|
extract::{Form, Path, State},
|
||||||
http::StatusCode,
|
http::StatusCode,
|
||||||
response::{IntoResponse, Redirect, Response},
|
response::{IntoResponse, Redirect, Response},
|
||||||
};
|
};
|
||||||
|
@ -8,7 +8,7 @@ use julid::Julid;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use sqlx::{query, query_as, query_scalar, SqlitePool};
|
use sqlx::{query, query_as, query_scalar, SqlitePool};
|
||||||
|
|
||||||
use super::templates::{AddNewWatchPage, AddWatchButton, GetWatchPage, SearchWatchesPage};
|
use super::templates::{AddNewWatchPage, AddWatchButton, GetWatchPage};
|
||||||
use crate::{
|
use crate::{
|
||||||
misc_util::{empty_string_as_none, year_to_epoch},
|
misc_util::{empty_string_as_none, year_to_epoch},
|
||||||
AuthSession, MyWatchesPage, ShowKind, Watch, WatchQuest,
|
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 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_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 =
|
const ADD_WATCH_QUEST_QUERY: &str =
|
||||||
"insert into watch_quests (user, watch, public, watched) values ($1, $2, $3, $4)";
|
"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
|
// 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?
|
// kinda the main form?
|
||||||
#[derive(Debug, Default, Deserialize, PartialEq, Eq)]
|
#[derive(Debug, Default, Deserialize, PartialEq, Eq)]
|
||||||
pub struct PostAddNewWatch {
|
pub struct PostAddNewWatch {
|
||||||
|
@ -239,34 +224,6 @@ pub async fn get_watches(auth: AuthSession, State(pool): State<SqlitePool>) -> i
|
||||||
MyWatchesPage { watches, user }
|
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(
|
pub async fn get_watch_status(
|
||||||
auth: AuthSession,
|
auth: AuthSession,
|
||||||
State(pool): State<SqlitePool>,
|
State(pool): State<SqlitePool>,
|
||||||
|
|
|
@ -11,13 +11,6 @@ pub struct MyWatchesPage {
|
||||||
pub user: Option<User>,
|
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)]
|
#[derive(Debug, Default, Template, Deserialize, Serialize, PartialEq, Eq, OptionalOptionalUser)]
|
||||||
#[template(path = "get_watch_page.html")]
|
#[template(path = "get_watch_page.html")]
|
||||||
pub struct GetWatchPage {
|
pub struct GetWatchPage {
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for watch in watches %}
|
{% for res in results %}
|
||||||
{% include "watch-search-result.html" %}
|
{% include "watch-search-result.html" %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
<tr id="watchlist-item-{{watch.id}}">
|
<tr id="watchlist-item-{{res.id}}">
|
||||||
<td><span class="watchtitle"><a href="/watch/{{watch.id}}">{{watch.title}}</a></span></td>
|
<td><span class="watchtitle"><a href="/watch/{{res.id}}">{{res.title}}</a></span></td>
|
||||||
<td><span>
|
<td><span>
|
||||||
{% match watch.metadata_url %}
|
{% match res.metadata_url %}
|
||||||
{% when Some with (mdurl) %}
|
{% when Some with (mdurl) %}
|
||||||
<a href="{{ mdurl }}">{{ mdurl }}</a>
|
<a href="{{ mdurl }}">{{ mdurl }}</a>
|
||||||
{% when None %}
|
{% when None %}
|
||||||
{% endmatch %}
|
{% endmatch %}
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
<td>{{watch.kind}}</td>
|
<td>{{res.kind}}</td>
|
||||||
<td> {% call m::get_or_default(watch.year(), "when??") -%}</td>
|
<td> {% call m::get_or_default(res.year(), "when??") -%}</td>
|
||||||
<td>
|
<td>
|
||||||
<span id="add-watch-{{watch.id}}">
|
<span id="add-watch-{{res.id}}">
|
||||||
<span hx-get="/watch/status/{{watch.id}}" hx-target="this" hx-trigger="load, reveal"
|
<span hx-get="/watch/status/{{res.id}}" hx-target="this" hx-trigger="load, reveal"
|
||||||
hx-swap="outerHTML">???</span>
|
hx-swap="outerHTML">???</span>
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
|
|
Loading…
Reference in a new issue