diff --git a/backend/api/src/lib.rs b/backend/api/src/lib.rs index a8236a7..462739d 100644 --- a/backend/api/src/lib.rs +++ b/backend/api/src/lib.rs @@ -636,12 +636,13 @@ async fn list_book( let page: usize = params.get("page").unwrap().parse().unwrap(); let userid: i32 = params.get("userid").unwrap().parse().unwrap(); let sort: String = params.get("sort").unwrap().to_string(); + let per_page: usize = 12; - let books = QueryCore::find_books_plus_meta_in_page(conn,page,12,userid, sort) + let books = QueryCore::find_books_plus_meta_in_page(conn,page,per_page,userid, sort) .await .expect("could not list books"); -let mut resbooks: Vec = Vec::with_capacity(12); +let mut resbooks: Vec = Vec::with_capacity(per_page); for bookandmeta in books.0.into_iter() { let mut cover = bookandmeta.clone().book.cover; diff --git a/frontend/css/index.css b/frontend/css/index.css index c29ee74..61c1128 100644 --- a/frontend/css/index.css +++ b/frontend/css/index.css @@ -75,7 +75,7 @@ body { /* Float three header columns side by side */ .header-column { float: left; - width: 25%; + width: 36%; padding: 0 10px; } /* Float three header columns side by side */ diff --git a/frontend/src/main.rs b/frontend/src/main.rs index 43160cb..4582e72 100644 --- a/frontend/src/main.rs +++ b/frontend/src/main.rs @@ -86,12 +86,14 @@ pub struct AppState { pub deleterequest: RcSignal, pub userlist: RcSignal>, pub userid: RcSignal, + pub selectedusername: RcSignal, pub useridloggedin: RcSignal, pub userscreen: RcSignal, pub loggedin: RcSignal, pub editmode: RcSignal, pub dropdownselect: RcSignal, pub scrolling: RcSignal, + pub scrollevent: RcSignal, } async fn login_user(user: AxumUser) -> Result { @@ -219,6 +221,7 @@ pub fn Header(cx: Scope) -> View { let value3 = create_signal(cx, String::new()); let input_ref3 = create_node_ref(cx); + let completed = create_selector(cx, || *app_state.editmode.get()); let editchecked = create_signal(cx, false); @@ -312,6 +315,7 @@ pub fn Header(cx: Scope) -> View { let toggle_editmode = |_| { app_state.editmode.set(*editchecked.get()); app_state.userid.set(*app_state.useridloggedin.get()); + app_state.selectedusername.set("SELF".to_string()); }; let dropdown_userselect = |_| { @@ -351,26 +355,13 @@ pub fn Header(cx: Scope) -> View { } }) } - (if *app_state.editmode.get() == true { - view!{ cx, - div(class="header-column"){ - input(ref=input_ref, - class="new-todo", - placeholder="Search internet (openlibrary)", - bind:value=value, - on:keyup=handle_submit, - ) - } } - } else { - view!{cx, } - }) div(class="header-column"){ (if *app_state.editmode.get() == false { view!{ cx, div(class="dropdown"){ - button(on:click=dropdown_userselect) { "Select User" } + button(on:click=dropdown_userselect) { "Choose Collection" } (if *app_state.dropdownselect.get() == true { view!{ cx, div(class="dropdown-content") { @@ -390,28 +381,42 @@ pub fn Header(cx: Scope) -> View { view!{cx, ""} }) - button(on:click=click_listall) { "All books" } - input(ref=input_ref2, - class="new-todo", - placeholder="Search your library", - bind:value=value2, - on:keyup=handle_submit_seachall, - ) + (if *app_state.userid.get() != 0 { + view!{ cx, + (format!(" {} ", *app_state.selectedusername.get())) + button(on:click=click_listall) { "All books" } + input(ref=input_ref2, + class="new-todo", + placeholder="Search your library", + bind:value=value2, + on:keyup=handle_submit_seachall, + ) + }} else { + view!{cx, "No Collection Selected"} + }) } + (if *app_state.editmode.get() == true { view!{ cx, - div(class="header-column"){ + div(class="header-column"){ + input(ref=input_ref, + class="new-todo", + placeholder="Search internet (openlibrary)", + bind:value=value, + on:keyup=handle_submit, + ) - button(on:click=click_addbook) { "+ Add New" } + + button(on:click=click_addbook) { "+ Add New" } input(ref=input_ref3, class="new-todo", placeholder="Add bulk ISBNs", bind:value=value3, on:keyup=handle_submit_addbulk, ) - } - } } else { + } + }} else { view!{cx, ""} }) @@ -430,6 +435,7 @@ pub fn DropDownUser(cx: Scope, value: StringProp) -> View { let handle_select_user = move |_| { app_state.userid.set( *(*app_state.userlist.get()).get(&(valueclosure.value).clone()).unwrap_or(&0)); + app_state.selectedusername.set(valueclosure.value.clone()); app_state.dropdownselect.set(false); }; @@ -441,23 +447,33 @@ pub fn DropDownUser(cx: Scope, value: StringProp) -> View { #[component] async fn ListDB(cx: Scope<'_>) -> View { let app_state = use_context::(cx); + let app_state2 = app_state.clone(); + + //provide_context(cx, false); //let callback_signal = use_context::>(cx); -/* + //let csignal = callback_signal.clone(); + //let csignal2 = callback_signal.clone(); + create_effect(cx, || { let app_state = app_state.clone(); - let cxsignal = callback_signal.clone(); - if *cxsignal.get() == true { - cxsignal.set(false); - if *app_state.pagedisplay.get() < *app_state.maxpage.get()-1 { + //let csignal2 = csignal2.clone(); + if *app_state.scrollevent.get() == true { + app_state.scrollevent.set(false); + info!("Scroll event result {}{}",*app_state.pagedisplay.get(), *app_state.maxpage.get() ); + if *app_state.pagedisplay.get() < *app_state.maxpage.get() { app_state.pagedisplay.set(*app_state.pagedisplay.get()+1); app_state.scrolling.set(true); + info!("Scroll update needed"); + } } }); -*/ + create_effect(cx, || { let app_state = app_state.clone(); + let app_state_scr = app_state.clone(); app_state.search.track(); + app_state.scrolling.track(); app_state.pagenum.track(); app_state.openlibrary.track(); app_state.internalsearch.track(); @@ -473,7 +489,6 @@ async fn ListDB(cx: Scope<'_>) -> View { if *app_state.openlibrary.get() == false { if *app_state.refreshing.get() == true { - app_state.refreshing.set(false); app_state.books.set(Vec::new()); //TimeoutFuture::new(1000).await; //info!("Refresh triggered"); @@ -505,40 +520,40 @@ async fn ListDB(cx: Scope<'_>) -> View { ) }); } + app_state.refreshing.set(false); } else if *app_state.scrolling.get()==true { - app_state.scrolling.set(false); if *app_state.internalsearch.get() == false { - info!("DB triggered"); + info!("DB triggered2"); spawn_local(async move { - let res = list_books(*app_state.pagedisplay.get(), *app_state.userid.get(), "desc".to_string()) + let res = list_books(*app_state_scr.pagedisplay.get(), *app_state_scr.userid.get(), "desc".to_string()) .await.unwrap(); - let mut currbooks = (*app_state.clone().books.get()).clone(); + let mut currbooks = (*app_state_scr.clone().books.get()).clone(); currbooks.extend(res.books.iter().cloned()); - app_state.books.set( + app_state_scr.books.set( currbooks ); - app_state.maxpage.set( + app_state_scr.maxpage.set( res.num_pages ) }); } else { - info!("IntSearch triggered"); + info!("IntSearch triggered2"); spawn_local(async move { - let res = search_books(app_state.search.get().to_string(), *app_state.pagedisplay.get(), *app_state.userid.get()) + let res = search_books(app_state_scr.search.get().to_string(), *app_state_scr.pagedisplay.get(), *app_state_scr.userid.get()) .await.unwrap(); - let mut currbooks = (*app_state.clone().books.get()).clone(); + let mut currbooks = (*app_state_scr.clone().books.get()).clone(); currbooks.extend(res.books.iter().cloned()); - app_state.books.set( + app_state_scr.books.set( currbooks ); - app_state.maxpage.set( + app_state_scr.maxpage.set( res.num_pages ) }); } - + app_state.scrolling.set(false); } } else { @@ -562,8 +577,16 @@ async fn ListDB(cx: Scope<'_>) -> View { }); + let handle_load_more = move |_| { + let app_state = app_state.clone(); + app_state.scrollevent.set(true); + }; + let callback: Closure = Closure::new(move || { - //let csignal = callback_signal.clone(); + //let csignal = csignal.clone(); + //csignal.set(true); + let app_state2 = app_state2.clone(); + app_state2.scrollevent.set(true); info!("Got scroll event"); }); @@ -606,6 +629,13 @@ async fn ListDB(cx: Scope<'_>) -> View { view!{cx, ""} } ) + br{} + (if *app_state.maxpage.get() > 1 && *app_state.maxpage.get() > *app_state.pagedisplay.get() { + view!{ cx, + button(on:click=handle_load_more){ "Load More" } + }} else { + view!{ cx, ""} + }) } } } @@ -1198,10 +1228,11 @@ async fn PageBar(cx: Scope<'_>) -> View { let input_ref = create_node_ref(cx); let handle_add = move |_| { - if *app_state.pagenum.get() < *app_state.maxpage.get()-1 { + if *app_state.pagenum.get() < *app_state.maxpage.get() { app_state.pagenum.set(*app_state.pagenum.get()+1); app_state.pagedisplay.set(*app_state.pagenum.get()+1); app_state.refreshing.set(true); + currpg.set((*app_state.pagenum.get()).to_string()); } }; @@ -1210,6 +1241,7 @@ async fn PageBar(cx: Scope<'_>) -> View { app_state.pagenum.set(*app_state.pagenum.get()-1); app_state.pagedisplay.set(*app_state.pagenum.get()-1); app_state.refreshing.set(true); + currpg.set((*app_state.pagenum.get()).to_string()); } }; @@ -1218,7 +1250,7 @@ async fn PageBar(cx: Scope<'_>) -> View { if event.key() == "Enter" { let pg = currpg.get().as_ref().clone().parse::().unwrap_or(1); - if pg>0 && pg<*app_state.maxpage.get() { + if pg>0 && pg<=*app_state.maxpage.get() { app_state.pagenum.set(pg); app_state.pagedisplay.set(pg); app_state.refreshing.set(true); @@ -1296,6 +1328,7 @@ async fn LoginScreenUI(cx: Scope<'_>) -> View { let auth = authentication_check().await.unwrap_or(false); app_state.loggedin.set(auth); if auth == true { + app_state.selectedusername.set(userstr.clone()); app_state.useridloggedin.set( *(*app_state.userlist.get()).get(&userstr).unwrap_or(&0)); app_state.userid.set( *(*app_state.userlist.get()).get(&userstr).unwrap_or(&0)); app_state.userscreen.set(false); @@ -1303,6 +1336,33 @@ async fn LoginScreenUI(cx: Scope<'_>) -> View { }); }; + let handle_submit_login = |event: Event| { + let event: KeyboardEvent = event.unchecked_into(); + + if event.key() == "Enter" { + let app_state = app_state.clone(); + let userstr = (*userval.get()).clone(); + let user = AxumUser{ + id: 0, + name: (*userval.get()).clone(), + password_hash: (*passval.get()).clone(), + }; + spawn_local(async move { + login_user(user) + .await.expect("Couldn't login user"); + let auth = authentication_check().await.unwrap_or(false); + app_state.loggedin.set(auth); + if auth == true { + app_state.selectedusername.set(userstr.clone()); + app_state.useridloggedin.set( * ((*app_state.userlist.get()).get(&userstr).unwrap_or(&0)) ); + info!("ID LOGGED IN {} {:?}",*app_state.useridloggedin.get(),*app_state.userlist.get()); + app_state.userid.set( *(*app_state.userlist.get()).get(&userstr).unwrap_or(&0)); + app_state.userscreen.set(false); + } + }); + } + }; + create_effect(cx, || { if *app_state.userscreen.get() == true { let dom_node = node_ref.try_get::(); @@ -1331,9 +1391,13 @@ async fn LoginScreenUI(cx: Scope<'_>) -> View { (if *app_state.userscreen.get() == true { view!{cx, div(class="modal-content"){ + label{"User name : "} input(ref=input_refU,bind:value=userval) - input(ref=input_refP,bind:value=passval,type="password") - + br{} + label{"Password : "} + input(ref=input_refP,bind:value=passval,type="password", + on:keyup=handle_submit_login) + br{} button(on:click=handle_login){ "LOGIN" } button(on:click=handle_register){ "REGISTER" } button(class="close", on:click=handle_close){ "CLOSE" } @@ -1371,12 +1435,14 @@ fn App(cx: Scope) -> View { deleterequest: create_rc_signal(bool::default()), userlist: create_rc_signal(HashMap::new()), userid: create_rc_signal(0), + selectedusername: create_rc_signal(String::new()), useridloggedin: create_rc_signal(0), userscreen: create_rc_signal(bool::default()), loggedin: create_rc_signal(bool::default()), editmode: create_rc_signal(bool::default()), dropdownselect: create_rc_signal(bool::default()), scrolling: create_rc_signal(bool::default()), + scrollevent: create_rc_signal(bool::default()), }; provide_context(cx, app_state);