From ca6e6e88ce0e583a054fa681451890b03fe47708 Mon Sep 17 00:00:00 2001 From: Vinod J M Date: Sun, 1 Jan 2023 23:45:43 +0530 Subject: [PATCH] user-auth store frontend and backend v4 --- frontend/Cargo.toml | 2 +- frontend/css/index.css | 3 +- frontend/src/main.rs | 177 ++++++++++++++++++++++++++++++----------- 3 files changed, 135 insertions(+), 47 deletions(-) diff --git a/frontend/Cargo.toml b/frontend/Cargo.toml index ac138f6..59f5eef 100644 --- a/frontend/Cargo.toml +++ b/frontend/Cargo.toml @@ -31,5 +31,5 @@ wasm-bindgen = "0.2.79" #yew-router = "0.16.0" [dependencies.web-sys] -features = ["InputEvent", "KeyboardEvent", "Location", "Storage"] +features = ["InputEvent", "EventTarget", "MouseEvent", "KeyboardEvent", "Location", "Storage", "Element"] version = "0.3.56" diff --git a/frontend/css/index.css b/frontend/css/index.css index 61c1128..bf6e2f2 100644 --- a/frontend/css/index.css +++ b/frontend/css/index.css @@ -44,6 +44,7 @@ body { /* Dropdown Content (Hidden by Default) */ .dropdown-content { + /* margin-top: 80px; Add a top margin to avoid content overlay */ position: absolute; min-width: 160px; z-index: 1; @@ -211,7 +212,7 @@ body { } .page-input { - width: 40px; + width: 30px; } /* Responsive columns - one column layout (vertical) on small screens */ diff --git a/frontend/src/main.rs b/frontend/src/main.rs index 4582e72..199cea6 100644 --- a/frontend/src/main.rs +++ b/frontend/src/main.rs @@ -9,7 +9,7 @@ use sycamore::prelude::*; //use sycamore::suspense::Suspense; //use sycamore_router::Route; use wasm_bindgen::JsCast; -use web_sys::{Event, HtmlInputElement, KeyboardEvent}; // 0.3.5 +use web_sys::{Event, HtmlInputElement, KeyboardEvent, EventTarget}; // 0.3.5 use dotenv_codegen::dotenv; use itertools::Itertools; use std::collections::HashMap; @@ -87,6 +87,7 @@ pub struct AppState { pub userlist: RcSignal>, pub userid: RcSignal, pub selectedusername: RcSignal, + pub loggedusername: RcSignal, pub useridloggedin: RcSignal, pub userscreen: RcSignal, pub loggedin: RcSignal, @@ -313,9 +314,10 @@ pub fn Header(cx: Scope) -> View { }; let toggle_editmode = |_| { - app_state.editmode.set(*editchecked.get()); + //app_state.editmode.set(*editchecked.get()); + app_state.editmode.set( !(*app_state.editmode.get()) ); app_state.userid.set(*app_state.useridloggedin.get()); - app_state.selectedusername.set("SELF".to_string()); + app_state.selectedusername.set((*app_state.loggedusername.get()).clone()); }; let dropdown_userselect = |_| { @@ -341,7 +343,7 @@ pub fn Header(cx: Scope) -> View { div(class="header-button"){ (if *app_state.loggedin.get() == false { view!{ cx, - button(on:click=click_userscreen) { "Register/Login" } + button(on:click=click_userscreen) { "Register / Login" } } } else { view!{cx, @@ -357,11 +359,26 @@ pub fn Header(cx: Scope) -> View { } div(class="header-column"){ + + + (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 collection", + bind:value=value2, + on:keyup=handle_submit_seachall, + ) + }} else { + view!{cx, "No Collection Selected"} + }) + br{} (if *app_state.editmode.get() == false { view!{ cx, div(class="dropdown"){ - button(on:click=dropdown_userselect) { "Choose Collection" } (if *app_state.dropdownselect.get() == true { view!{ cx, div(class="dropdown-content") { @@ -376,37 +393,16 @@ pub fn Header(cx: Scope) -> View { } else { view!{cx, ""} }) + button(on:click=dropdown_userselect) { "Choose Collection" } } }} else { view!{cx, ""} }) - - (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"){ - 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" } input(ref=input_ref3, @@ -415,6 +411,15 @@ pub fn Header(cx: Scope) -> View { bind:value=value3, on:keyup=handle_submit_addbulk, ) + br{} + 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, ""} @@ -454,6 +459,18 @@ async fn ListDB(cx: Scope<'_>) -> View { //let csignal = callback_signal.clone(); //let csignal2 = callback_signal.clone(); + + create_effect(cx, || { + let app_state = app_state.clone(); + if *app_state.userid.get() != 0 { + app_state.openlibrary.set(false); + app_state.internalsearch.set(false); + app_state.pagenum.set(1); + app_state.pagedisplay.set(1); + app_state.refreshing.set(true); + } + }); + create_effect(cx, || { let app_state = app_state.clone(); //let csignal2 = csignal2.clone(); @@ -646,6 +663,7 @@ pub fn BookDB(cx: Scope, bookitem: BookUIProp) -> View { let bookdelete = bookitem.bookitem.clone(); let bookupdate = bookitem.bookitem.clone(); let bookdisplay = bookitem.bookitem.clone(); + let bookdisplay_div = bookitem.bookitem.clone(); let loctitle = bookitem.bookitem.clone().title.clone(); let locauthors = bookitem.bookitem.clone().author_name.clone().unwrap_or(vec!["".to_string()]).join(", "); let locdesc = bookitem.bookitem.clone().description.unwrap_or("".to_string()); @@ -685,6 +703,12 @@ pub fn BookDB(cx: Scope, bookitem: BookUIProp) -> View { app_state.updating.set(false); //info!("Setting displaying book {:?}",bookdisplay); app_state.displayingbook.set(bookdisplay.clone()); + }; + let handle_display_div = move |_| { + app_state.displaying.set(true); + app_state.updating.set(false); + //info!("Setting displaying book {:?}",bookdisplay); + app_state.displayingbook.set(bookdisplay_div.clone()); }; view! { cx, div(class="column"){ @@ -696,7 +720,7 @@ pub fn BookDB(cx: Scope, bookitem: BookUIProp) -> View { button(class="update", on:click=handle_update){ "EDIT=" } button(class="info", on:click=handle_display){ "INFO+" } } - div(class="card-main"){ + div(class="card-main",on:click=handle_display_div){ img(src=coverurl,width="100") div(class="card-title"){ @@ -705,15 +729,14 @@ pub fn BookDB(cx: Scope, bookitem: BookUIProp) -> View { div(class="card-authors"){ (format!("{}",locauthors)) } - //div(class="card-image"){ - //} - } - div(class="card-desc"){ (format!("{}",locloc)) br{}br{} (format!("{}",locdesc)) } + } + + } } @@ -725,6 +748,7 @@ pub fn BookDB(cx: Scope, bookitem: BookUIProp) -> View { pub fn BookDB_View(cx: Scope, bookitem: BookUIProp) -> View { let app_state = use_context::(cx); let bookdisplay = bookitem.bookitem.clone(); + let bookdisplay_div = bookitem.bookitem.clone(); let loctitle = bookitem.bookitem.clone().title.clone(); let locauthors = bookitem.bookitem.clone().author_name.clone().unwrap_or(vec!["".to_string()]).join(", "); let locdesc = bookitem.bookitem.clone().description.unwrap_or("".to_string()); @@ -737,6 +761,12 @@ pub fn BookDB_View(cx: Scope, bookitem: BookUIProp) -> View { //info!("Setting displaying book {:?}",bookdisplay); app_state.displayingbook.set(bookdisplay.clone()); }; + let handle_display_div = move |_| { + app_state.displaying.set(true); + app_state.updating.set(false); + //info!("Setting displaying book {:?}",bookdisplay); + app_state.displayingbook.set(bookdisplay_div.clone()); + }; view! { cx, div(class="column"){ div(class="card"){ @@ -745,7 +775,7 @@ pub fn BookDB_View(cx: Scope, bookitem: BookUIProp) -> View { button(class="info", on:click=handle_display){ "INFO+" } } - div(class="card-main"){ + div(class="card-main", on:click=handle_display_div){ img(src=coverurl,width="100") div(class="card-title"){ @@ -754,15 +784,14 @@ pub fn BookDB_View(cx: Scope, bookitem: BookUIProp) -> View { div(class="card-authors"){ (format!("{}",locauthors)) } - //div(class="card-image"){ - //} - } div(class="card-desc"){ (format!("{}",locloc)) br{}br{} (format!("{}",locdesc)) } + } + } } @@ -811,19 +840,28 @@ async fn ListOL(cx: Scope<'_>) -> View { #[component(inline_props)] pub fn BookOL(cx: Scope, bookitem: BookUIProp) -> View { let book = bookitem.bookitem.clone(); + let book_div=book.clone(); let bookdisp=book.clone(); let loctitle = bookitem.bookitem.clone().title.clone(); let locauthors = bookitem.bookitem.clone().author_name.clone().unwrap_or(vec!["".to_string()]).join(", "); - let coverurl = bookdisp.cover.clone().unwrap_or("NONE".to_string()); + let backend_url : &'static str = dotenv!("BACKEND_URL"); + let mut coverurl = bookdisp.cover.clone().unwrap_or("NONE".to_string()); + if coverurl == "NONE".to_string() { + coverurl = format!("{}/images/placeholder.jpg", backend_url ); + } + let app_state = use_context::(cx); let handle_add = move |_| { app_state.adding.set(true); app_state.addingbook.set(book.clone()); }; - + let handle_add_div = move |_| { + app_state.adding.set(true); + app_state.addingbook.set(book_div.clone()); + }; view! { cx, div(class="column"){ - div(class="card-openlibrary"){ + div(class="card-openlibrary",on:click=handle_add_div){ button(class="add", on:click=handle_add){ "ADD+" } div(class="card-main"){ img(src=coverurl,width="100") @@ -982,8 +1020,22 @@ info!("Adding book"); } }); + let handle_click_close = |event: Event| { + let target: EventTarget = event.target().unwrap(); + let element: web_sys::Element = target.unchecked_into(); + if element.has_attribute("closable") + { + app_state.displaying.set(false); + + let dom_node = node_ref.try_get::(); + if dom_node.is_some() { + dom_node.unwrap().set_attribute("popup-display","false"); + } + } + }; + view! {cx, - div(class="modal-box",ref=node_ref){ + div(class="modal-box",ref=node_ref, on:click=handle_click_close, closable="true"){ (if *app_state.adding.get() == true || *app_state.updating.get() == true { view!{ cx, @@ -1154,9 +1206,22 @@ async fn SelectedUI(cx: Scope<'_>) -> View { } }); + let handle_click_close = |event: Event| { + let target: EventTarget = event.target().unwrap(); + let element: web_sys::Element = target.unchecked_into(); + if element.has_attribute("closable") + { + app_state.displaying.set(false); + + let dom_node = node_ref.try_get::(); + if dom_node.is_some() { + dom_node.unwrap().set_attribute("popup-display","false"); + } + } + }; view! {cx, - div(class="modal-box", ref=node_ref){ + div(class="modal-box", ref=node_ref, on:click=handle_click_close, closable="true"){ (if *app_state.displaying.get() == true { view!{ cx, @@ -1262,7 +1327,7 @@ async fn PageBar(cx: Scope<'_>) -> View { }; view! {cx, div { - (if *app_state.openlibrary.get() == false || *app_state.internalsearch.get() == true { + (if (*app_state.openlibrary.get() == false || *app_state.internalsearch.get() == true) && !app_state.books.get().is_empty() { view!{ cx, label{"PAGE "} input(ref=input_ref,bind:value=currpg,on:keyup=handle_submit,class="page-input") @@ -1322,12 +1387,16 @@ async fn LoginScreenUI(cx: Scope<'_>) -> View { name: (*userval.get()).clone(), password_hash: (*passval.get()).clone(), }; + spawn_local(async move { + app_state.userlist.set(list_users() + .await.expect("Couldn't list user")); 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.loggedusername.set(userstr.clone()); 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)); @@ -1348,14 +1417,16 @@ async fn LoginScreenUI(cx: Scope<'_>) -> View { password_hash: (*passval.get()).clone(), }; spawn_local(async move { + app_state.userlist.set(list_users() + .await.expect("Couldn't list user")); 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.loggedusername.set(userstr.clone()); 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); } @@ -1377,7 +1448,7 @@ async fn LoginScreenUI(cx: Scope<'_>) -> View { } }); let handle_close = move |_| { - app_state.displaying.set(false); + app_state.userscreen.set(false); let dom_node = node_ref.try_get::(); if dom_node.is_some() { @@ -1385,8 +1456,23 @@ async fn LoginScreenUI(cx: Scope<'_>) -> View { } }; + + let handle_click_close = |event: Event| { + let target: EventTarget = event.target().unwrap(); + let element: web_sys::Element = target.unchecked_into(); + if element.has_attribute("closable") + { + app_state.userscreen.set(false); + + let dom_node = node_ref.try_get::(); + if dom_node.is_some() { + dom_node.unwrap().set_attribute("popup-display","false"); + } + } + }; + view! {cx, - div(class="modal-box", ref=node_ref){ + div(class="modal-box", ref=node_ref, on:click=handle_click_close, closable="true"){ (if *app_state.userscreen.get() == true { view!{cx, @@ -1436,6 +1522,7 @@ fn App(cx: Scope) -> View { userlist: create_rc_signal(HashMap::new()), userid: create_rc_signal(0), selectedusername: create_rc_signal(String::new()), + loggedusername: create_rc_signal(String::new()), useridloggedin: create_rc_signal(0), userscreen: create_rc_signal(bool::default()), loggedin: create_rc_signal(bool::default()),