rebuilt app as struct component, fixed futures

This commit is contained in:
Bart Massey 2024-06-02 20:57:49 -07:00
parent 2af8ba5c15
commit eb45baf455
3 changed files with 85 additions and 76 deletions

View File

@ -1,12 +1,6 @@
use crate::*; use crate::*;
#[derive(Properties, Clone, PartialEq)] pub fn acquire_cookie() -> String {
pub struct CookieProps {
pub cookie: String,
}
impl CookieProps {
pub fn acquire_cookie() -> Self {
let cookie_options = cookies::CookieOptions::default() let cookie_options = cookies::CookieOptions::default()
.expires_after(core::time::Duration::from_secs( .expires_after(core::time::Duration::from_secs(
52 * 7 * 24 * 60 * 60 52 * 7 * 24 * 60 * 60
@ -14,7 +8,7 @@ impl CookieProps {
match cookies::get("test") { match cookies::get("test") {
Some(Ok(cookie)) => { Some(Ok(cookie)) => {
log!("got cookie"); log!("got cookie");
return Self { cookie: cookie }; return cookie;
} }
Some(Err(e)) => { Some(Err(e)) => {
log!(format!("cookie error: {}", e)); log!(format!("cookie error: {}", e));
@ -25,18 +19,13 @@ impl CookieProps {
} }
log!("setting cookie"); log!("setting cookie");
cookies::set("test", "123", &cookie_options); cookies::set("test", "123", &cookie_options);
let cookie = "123".to_string(); "123".to_string()
// XXX Don't do this!! No secrets in logs!
// log!(&cookie);
Self { cookie }
}
} }
#[function_component(Cookie)] pub fn render_cookie(cookie: &str) -> Html {
pub fn cookie(CookieProps { cookie }: &CookieProps) -> Html {
html! { html! {
<div> <div>
<p>{cookie.clone()}</p> <p>{cookie}</p>
</div> </div>
} }
} }

View File

@ -10,13 +10,19 @@ pub struct JokeStruct {
} }
impl JokeStruct { impl JokeStruct {
pub async fn get_joke() -> Result<Self, gloo_net::Error> { pub async fn get_joke() -> Msg {
http::Request::get("http://localhost:3000/api/v1/joke") let response = http::Request::get("http://localhost:3000/api/v1/joke")
.send() .send()
.await? .await;
.json() match response {
.await Err(e) => Msg::GotJoke(Err(e)),
Ok(data) => Msg::GotJoke(data.json().await),
} }
}
}
pub fn format_tags(tags: &HashSet<String>) -> String {
let taglist: Vec<&str> = tags.iter().map(String::as_ref).collect();
taglist.join(", ")
} }
#[derive(Properties, Clone, PartialEq, serde::Deserialize)] #[derive(Properties, Clone, PartialEq, serde::Deserialize)]
@ -24,27 +30,23 @@ pub struct JokeProps {
pub joke: JokeStruct, pub joke: JokeStruct,
} }
pub fn format_tags(tags: &HashSet<String>) -> String {
let taglist: Vec<&str> = tags.iter().map(String::as_ref).collect();
taglist.join(", ")
}
#[function_component(Joke)] #[function_component(Joke)]
pub fn joke(joke: &JokeProps) -> Html { pub fn joke(joke: &JokeProps) -> Html {
let joke = &joke.joke;
html! { <> html! { <>
<div class="joke"> <div class="joke">
<span class="teller">{"Knock-Knock!"}</span><br/> <span class="teller">{"Knock-Knock!"}</span><br/>
<span class="tellee">{"Who's there?"}</span><br/> <span class="tellee">{"Who's there?"}</span><br/>
<span class="teller">{joke.joke.whos_there.clone()}</span><br/> <span class="teller">{joke.whos_there.clone()}</span><br/>
<span class="tellee">{format!("{} who?", &joke.joke.whos_there)}</span><br/> <span class="tellee">{format!("{} who?", &joke.whos_there)}</span><br/>
<span class="teller">{joke.joke.answer_who.clone()}</span> <span class="teller">{joke.answer_who.clone()}</span>
</div> </div>
<span class="annotation"> <span class="annotation">
{format!("[id: {}", &joke.joke.id)} {format!("[id: {}", &joke.id)}
if let Some(ref tags) = joke.joke.tags { if let Some(ref tags) = joke.tags {
{format!("; tags: {}", &format_tags(tags))} {format!("; tags: {}", &format_tags(tags))}
} }
if let Some(ref source) = joke.joke.source { if let Some(ref source) = joke.source {
{format!("; source: {}", source)} {format!("; source: {}", source)}
} }
{"]"} {"]"}

View File

@ -13,38 +13,56 @@ extern crate wasm_bindgen_futures;
use wasm_cookies as cookies; use wasm_cookies as cookies;
use yew::prelude::*; use yew::prelude::*;
#[function_component(App)] pub type JokeResult = Result<JokeStruct, gloo_net::Error>;
fn app() -> Html {
let cookie = use_state(|| CookieProps::acquire_cookie());
let joke = use_state(|| Err(gloo_net::Error::GlooError("uninit".to_string()))); struct App {
let get_joke = joke.clone(); cookie: String,
use_effect_with((), move |()| { joke: JokeResult,
wasm_bindgen_futures::spawn_local(async move { }
let joke = JokeStruct::get_joke().await;
get_joke.set(joke);
});
|| ()
});
pub enum Msg {
GotJoke(JokeResult),
}
impl Component for App {
type Message = Msg;
type Properties = ();
fn create(ctx: &Context<Self>) -> Self {
let cookie = acquire_cookie();
let got_joke = JokeStruct::get_joke();
ctx.link().send_future(got_joke);
let joke = Err(gloo_net::Error::GlooError("Loading Joke…".to_string()));
Self { cookie, joke }
}
fn update(&mut self, _ctx: &Context<Self>, msg: Self::Message) -> bool {
match msg {
Msg::GotJoke(joke) => self.joke = joke,
}
true
}
fn view(&self, _ctx: &Context<Self>) -> Html {
let cookie = &self.cookie;
let joke = &self.joke;
html! { html! {
<> <>
<h1>{ "Knock-Knock" }</h1> <h1>{ "Knock-Knock" }</h1>
if false { if false {
<div> {render_cookie(cookie)}
<Cookie cookie={cookie.cookie.clone()} />
</div>
} }
if let Ok(ref joke) = *joke { if let Ok(ref joke) = joke {
<Joke joke={joke.clone()}/> <Joke joke={joke.clone()}/>
} }
if let Err(ref error) = *joke { if let Err(ref error) = joke {
<div> <div>
<span class="error">{format!("Server Error: {error}")}</span> <span class="error">{format!("Server Error: {error}")}</span>
</div> </div>
} }
</> </>
} }
}
} }
fn main() { fn main() {