From 3ea421154d6497ffda5383744329952937b80c8b Mon Sep 17 00:00:00 2001 From: Vinod J M Date: Fri, 28 Oct 2022 22:15:51 +0530 Subject: [PATCH] v0.10-frontend-intermediate --- frontend/Cargo.lock | 12 ++++ frontend/Cargo.toml | 2 + frontend/src/main.rs | 146 +++++++++++++++++++++++++++++++------------ 3 files changed, 119 insertions(+), 41 deletions(-) diff --git a/frontend/Cargo.lock b/frontend/Cargo.lock index af111e6..e18a83d 100644 --- a/frontend/Cargo.lock +++ b/frontend/Cargo.lock @@ -96,6 +96,7 @@ dependencies = [ "log", "reqwasm", "serde", + "serde-wasm-bindgen", "sycamore", "sycamore-router", "wasm-bindgen", @@ -452,6 +453,17 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "serde-wasm-bindgen" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cfc62771e7b829b517cb213419236475f434fb480eddd76112ae182d274434a" +dependencies = [ + "js-sys", + "serde", + "wasm-bindgen", +] + [[package]] name = "serde_derive" version = "1.0.144" diff --git a/frontend/Cargo.toml b/frontend/Cargo.toml index 4c97a78..d9d47f0 100644 --- a/frontend/Cargo.toml +++ b/frontend/Cargo.toml @@ -9,6 +9,7 @@ edition = "2021" console_error_panic_hook = "0.1.7" env_logger = "0.9.0" gloo-net = "^0.2" +#gloo-utils = {version = "0.1.5", features =["serde"]} log = "0.4" console_log = { version = "0.2", features = ["color"] } #reqwest = {version = "0.11.11", features = ["blocking", "json"]} @@ -16,6 +17,7 @@ reqwasm = {version = "0.5.0", features = ["json"]} wasm-bindgen-futures = "^0.4" wasm-logger = "0.2.0" serde = { version = "^1.0", features = ["derive"] } +serde-wasm-bindgen = "0.4" sycamore = {version = "0.8.0-beta.7", features = ["suspense"]} sycamore-router = "0.8.0-beta.7" wasm-bindgen = "0.2.79" diff --git a/frontend/src/main.rs b/frontend/src/main.rs index 651fbd9..45c830f 100644 --- a/frontend/src/main.rs +++ b/frontend/src/main.rs @@ -4,7 +4,7 @@ use reqwasm::http::Request; use serde::{Deserialize, Serialize}; use sycamore::futures::spawn_local; use sycamore::prelude::*; -use sycamore::suspense::Suspense; +//use sycamore::suspense::Suspense; use sycamore_router::Route; use wasm_bindgen::JsCast; use web_sys::{Event, HtmlInputElement, KeyboardEvent}; // 0.3.5 @@ -32,32 +32,13 @@ pub struct BookUI { isbn: Option>, } -#[derive(Deserialize, Serialize, Debug, Default, Clone, PartialEq, Hash, Eq)] -pub struct Docs { - id: u32, - key: String, - title: String, - first_publish_year: Option, - number_of_pages_median: Option, - isbn: Option>, - cover_i: Option, - author_name: Option>, - person: Option>, - place: Option>, - subject: Option>, - time: Option>, -} - -#[derive(Deserialize, Serialize, Debug, Default)] -pub struct Books { - num_found: u32, - docs: Vec, -} - #[derive(Debug, Default, Clone)] pub struct AppState { pub books: RcSignal>, pub search: RcSignal, + pub openlibrary: RcSignal, + pub adding: RcSignal, + pub addingbook: RcSignal, } #[derive(Route)] @@ -78,6 +59,26 @@ async fn fetch_books(search: String) -> Result, reqwasm::Error> { Ok(body) } +async fn add_book(record: BookUI) -> Result { + let url = format!("http://localhost:8081/api/create"); + let _resp = Request::post(&url).body(serde_wasm_bindgen::to_value(&record).unwrap()).send().await?; + Ok("OK".to_string()) +} + +async fn delete_book(id: i32) -> Result { + let url = format!("http://localhost:8081/api/delete/{}", id); + let _resp = Request::post(&url).send().await?; + Ok("OK".to_string()) +} + +async fn list_books() -> Result, reqwasm::Error> { + let url = format!("http://localhost:8081/api/list"); + let resp = Request::post(&url).send().await?; + println!("Fetching books\n"); + let body = resp.json::>().await?; + Ok(body) +} + #[component] pub fn Header(cx: Scope) -> View { let app_state = use_context::(cx); @@ -93,7 +94,7 @@ pub fn Header(cx: Scope) -> View { if !task.is_empty() { app_state.search.set(task); - + app_state.openlibrary.set(true); println!("Fetching search\n"); info!("Fetching search\n"); value.set("".to_string()); @@ -104,22 +105,72 @@ pub fn Header(cx: Scope) -> View { } } }; - + let click_listall = |_| (app_state.openlibrary.set(false)); + let click_addbook = |_| { + app_state.adding.set(true); + app_state.addingbook.set(BookUI::default()); + }; view! { cx, header(class="header") { - h1 { "todos" } + h1 { "Search OpenLibrary" } input(ref=input_ref, class="new-todo", placeholder="What needs to be done?", bind:value=value, on:keyup=handle_submit, ) + button(on:click=click_listall) { "List All DB" } + button(on:click=click_addbook) { "+ Add New" } + + } } } #[component] -async fn VisitsCount(cx: Scope<'_>) -> View { +async fn ListDB(cx: Scope<'_>) -> View { + let app_state = use_context::(cx); + create_effect(cx, || { + let app_state = app_state.clone(); + + if *app_state.openlibrary.get() == false { + spawn_local(async move { + app_state.books.set( + list_books() + .await + .unwrap(), + ) + }); + } + }); + + let docs = create_memo(cx, || app_state.books.get().iter().cloned().collect::>()); + view! {cx, + p { + (if *app_state.openlibrary.get() == false { + view!{ cx, + //span {(app_state.books.get().num_found)} + ul { + Keyed( + iterable=docs, + view=move |cx, x| view! { cx, + li { (format!("{:?}",x)) + } + }, + key =|x| x.id ) + } + } + } else { + view!{cx,""} + } + ) + } + } +} + + +#[component] +async fn ListOL(cx: Scope<'_>) -> View { let app_state = use_context::(cx); create_effect(cx, || { //info!( @@ -136,51 +187,64 @@ async fn VisitsCount(cx: Scope<'_>) -> View { ) }); }); - let state = create_signal(cx, 0i32); -// let increment = |x: Docs| (state.set(x.first_publish_year.unwrap().try_into().unwrap())); - let increment = |_| (state.set(2)); let docs = create_memo(cx, || app_state.books.get().iter().cloned().collect::>()); //let docs = create_signal(cx, vec![1, 2]); view! {cx, p { - (if !app_state.search.get().is_empty() { + (if *app_state.openlibrary.get() == true { view!{ cx, - //span {(app_state.books.get().num_found)} - ul { + ul { Keyed( iterable=docs, view=move |cx, x| view! { cx, li { (format!("{:?}",x)) - button(on:click=increment) { "+" } } }, key =|x| x.id ) } } + } else { + view!{cx,""} } - else { - view! { cx, span { "World" } } - }) + ) } } } +#[component] +async fn AddingUI(cx: Scope<'_>) -> View { + let app_state = use_context::(cx); + view! {cx, + p { +(if *app_state.adding.get() == true { + view!{ cx,"Hello" } + } else { + view!{cx,""} + } + ) + } + } +} + + #[component] fn App(cx: Scope) -> View { let app_state = AppState { books: create_rc_signal(Vec::new()), search: create_rc_signal(String::default()), + openlibrary: create_rc_signal(bool::default()), + adding: create_rc_signal(bool::default()), + addingbook: create_rc_signal(BookUI::default()), }; provide_context(cx, app_state); view! { cx, div { Header {} - p { "Page Visit Counter" } - Suspense(fallback=view! { cx, "Loading..." }) { - VisitsCount {} - } + AddingUI{} + ListOL {} + ListDB{} } } }