diff --git a/server/service/src/main.rs b/server/service/src/main.rs index 22a5b2a..9ca9da9 100644 --- a/server/service/src/main.rs +++ b/server/service/src/main.rs @@ -74,15 +74,6 @@ impl fmt::Display for Direction { write!(f, "{}", s) } } -#[derive(Copy, Clone, Debug, Default, Deserialize)] -struct Sort(Key, Direction); - -impl fmt::Display for Sort { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let s = format!("{} {}", self.0, self.1); - write!(f, "{}", s) - } -} #[actix_rt::main] async fn main() -> io::Result<()> { @@ -156,7 +147,8 @@ async fn search( struct NewQuery { page: Option, size: Option, - sort: Option, + sort_key: Option, + sort_dir: Option, type_: Option, } @@ -191,21 +183,20 @@ fn search_query( let page = query.page.unwrap_or(1); let key = query.sort_key.unwrap_or_default(); let direction = query.sort_dir.unwrap_or_default(); - let sort = Sort(key, direction); let size = cmp::min(100, query.size.unwrap_or(DEFAULT_SIZE)); let type_ = query.type_.as_ref().map_or("torrent", String::deref); let offset = size * (page - 1); - dbg!( - "query = {}, type = {}, page = {}, size = {}, sort = {:?}", - q, type_, page, size, sort + println!( + "query = {}, type = {}, page = {}, size = {}, sort_key = {}, sort_dir = {}", + q, type_, page, size, key, direction ); let res = if type_ == "file" { let results = torrent_file_search(conn, q, size, offset)?; serde_json::to_value(&results).unwrap() } else { - let results = torrent_search(conn, q, sort, size, offset)?; + let results = torrent_search(conn, q, key, direction, size, offset)?; serde_json::to_value(&results).unwrap() }; @@ -219,13 +210,14 @@ fn new_query( let page = query.page.unwrap_or(1); let size = cmp::min(100, query.size.unwrap_or(DEFAULT_SIZE)); - let sort = query.sort.unwrap_or_default(); + let key = query.sort_key.unwrap_or_default(); + let direction = query.sort_dir.unwrap_or_default(); let type_ = query.type_.as_ref().map_or("torrent", String::deref); let offset = size * (page - 1); dbg!( - "new, type = {}, page = {}, size = {}, sort = {:?}", - type_, page, size, sort + "new, type = {}, page = {}, size = {}, sort_key = {}, sort_dir = {}", + type_, page, size, key, direction ); let res = if type_ == "file" { @@ -254,33 +246,34 @@ struct Torrent { fn torrent_search( conn: r2d2::PooledConnection, query: &str, - sort: Sort, + key: Key, + direction: Direction, size: usize, offset: usize, ) -> Result, Error> { - let stmt_str = format!("select * from torrents where name like '%' || :query || '%' order by {} limit :offset, :size", sort); + // `key` and `direction` are already sanitized and should not be escaped: + let stmt_str = format!("select * from torrents where name like '%' || ?1 || '%' order by {} {} limit ?2, ?3", key, direction); let mut stmt = conn.prepare(&stmt_str)?; - let torrent_iter = stmt.query_map(params![ + let torrent_iter = stmt.query_map(params!{ query.replace(" ", "%"), offset.to_string(), size.to_string(), - ], - - |row| { + }, + |row| { let size: isize = row.get(2)?; println!("got size {:?}", size); Ok(Torrent { - infohash: row.get(0)?, - name: row.get(1)?, - size_bytes: row.get(2)?, - created_unix: row.get(3)?, - seeders: row.get(4)?, - leechers: row.get(5)?, - completed: row.get(6)?, - scraped_date: row.get(7)?, + infohash: row.get(0)?, + name: row.get(1)?, + size_bytes: row.get(2)?, + created_unix: row.get(3)?, + seeders: row.get(4)?, + leechers: row.get(5)?, + completed: row.get(6)?, + scraped_date: row.get(7)?, }) - }, + }, )?; let mut torrents = Vec::new(); diff --git a/server/ui/fuse.js b/server/ui/fuse.js index ff1e6d1..a78354a 100644 --- a/server/ui/fuse.js +++ b/server/ui/fuse.js @@ -41,7 +41,8 @@ Sparky.task('config', _ => { }); app = fuse.bundle('app').instructions('>index.tsx'); }); -Sparky.task('clean', _ => Sparky.src('dist/').clean('dist/')); +//Sparky.task('clean', _ => Sparky.src('dist/').clean('dist/')); +Sparky.task('clean', _ => {}); Sparky.task('env', _ => (isProduction = true)); Sparky.task('copy-assets', () => Sparky.src('assets/*.ico').dest('dist/')); Sparky.task('dev', ['clean', 'config', 'copy-assets'], _ => { diff --git a/server/ui/src/components/navbar.tsx b/server/ui/src/components/navbar.tsx index 8355cbe..a1d7cb7 100644 --- a/server/ui/src/components/navbar.tsx +++ b/server/ui/src/components/navbar.tsx @@ -76,6 +76,7 @@ export class Navbar extends Component { } searchChange(i: Navbar, event) { + console.log("in searchChange"); let searchParams: SearchParams = { q: event.target.value, page: 1, @@ -87,6 +88,7 @@ export class Navbar extends Component { } searchTypeChange(i: Navbar, event) { + console.log("in searchTypeChange"); let searchParams: SearchParams = { q: i.state.searchParams.q, page: 1, diff --git a/server/ui/src/components/search.tsx b/server/ui/src/components/search.tsx index 60e804b..9b1dfe6 100644 --- a/server/ui/src/components/search.tsx +++ b/server/ui/src/components/search.tsx @@ -11,27 +11,19 @@ interface State { searching: Boolean; } - -function buildSearchURL(sort_key, {state: { searchParams }) { - console.log("got search URL sort_key", sort_key, "searchParams", searchParams, "thing", searchParams); - - //let searchParams = thing.state.searchParams; - - - if (sort_key === searchParams.sort_key) { - const sort_dir = searchParams.sort_dir === "asc" ? "desc" : "asc"; - searchParams.sort_dir = sort_dir; - console.log("no change in sort key from", sort_key, "so switch direction instead.") +function buildSearchURL({state: { searchParams }}, key) { + let page, direction; + if (key === searchParams.sort_key) { + page = searchParams.page; + direction = searchParams.sort_dir === "Asc" ? "Desc" : "Asc"; } else { - console.log("change sort key from", searchParams.sort_key, "to", sort_key); - searchParams.sort_key = sort_key; + page = 1; + direction = "Desc"; } - const url = `/#/search/${searchParams.type_}/${searchParams.q}/${searchParams.page}/${searchParams.sort_key}/${searchParams.sort_dir}` - return url; + return `/#/search/${searchParams.type_}/${searchParams.q}/${page}/${key}/${direction}`; } export class Search extends Component { - state: State = { results: { torrents: [] @@ -51,7 +43,7 @@ export class Search extends Component { } componentDidMount() { - console.log("got props", this.props); + console.log("loading page, got match", this.props.match.params); this.state.searchParams = { page: Number(this.props.match.params.page), q: this.props.match.params.q, @@ -65,6 +57,7 @@ export class Search extends Component { // Re-do search if the props have changed componentDidUpdate(lastProps: any) { if (lastProps.match && lastProps.match.params !== this.props.match.params) { + console.log("updating component with sort_key", this.props.match.params.sort_key); this.state.searchParams = { page: Number(this.props.match.params.page), q: this.props.match.params.q, @@ -78,7 +71,6 @@ export class Search extends Component { } search() { - console.log("in search, state", this.state); if (!!this.state.searchParams.q) { this.setState({ searching: true, results: { torrents: [] } }); this.fetchData(this.state.searchParams) @@ -141,24 +133,33 @@ export class Search extends Component { + href={buildSearchURL(this, 'Name')}> Name + href={buildSearchURL(this, 'Size')}> Size - Seeds + + Seeds + - Leeches + + Leechers + - Scraped + + Scraped +