#![recursion_limit = "256"]
use anyhow::Error;
use eingang::models::Data;
use wasm_bindgen::prelude::*;
use yew::format::{Json, Nothing};
use yew::services::fetch::{FetchTask, Request, Response};
use yew::services::storage::{Area, StorageService};
use yew::services::{ConsoleService, DialogService};
use yew::{html, Component, ComponentLink, Html, ShouldRender};
const KEY: &str = "eingang.model.store";
type FetchResponse<T> = Response<Json<Result<T, Error>>>;
type SendResponse = Response<Result<String, Error>>;
struct Model {
link: ComponentLink<Self>,
storage: StorageService,
value: Data,
ft: Option<FetchTask>, st: Option<FetchTask>,
}
enum Msg {
AddOne,
SubtractOne,
SetValue,
FetchStart,
FetchSuccess(Data),
FetchFail,
SendStart,
SendSuccess,
SendFailed,
}
impl Component for Model {
type Message = Msg;
type Properties = ();
fn create(_: Self::Properties, link: ComponentLink<Self>) -> Self {
let storage = StorageService::new(Area::Local).expect("Allocation error");
let value = {
if let Json(Ok(val)) = storage.restore(KEY) {
ConsoleService::log("Restored!");
val
} else {
ConsoleService::log("Failed to restore!");
Default::default()
}
};
Self {
link,
storage,
value,
ft: None,
st: None,
}
}
fn update(&mut self, msg: Self::Message) -> ShouldRender {
match msg {
Msg::SendStart => {
let callback = self.link.callback(move |response: SendResponse| {
let (meta, _) = response.into_parts();
if meta.status.is_success() {
Msg::SendSuccess
} else {
Msg::SendFailed
}
});
let request = Request::post("http://localhost:8081/save")
.header("Content-Type", "application/json")
.body(Json(&self.value))
.unwrap();
let task = yew::services::FetchService::fetch(request, callback).unwrap();
self.st = Some(task);
}
Msg::SendSuccess => {
ConsoleService::log("Saved data!");
self.st = None
}
Msg::SendFailed => {
ConsoleService::log("Could not save data!");
DialogService::alert("Could not save data!");
self.st = None
}
Msg::FetchStart => {
let callback = self.link.callback(move |response: FetchResponse<Data>| {
let (meta, Json(result)) = response.into_parts();
if meta.status.is_success() {
Msg::FetchSuccess(result.ok().unwrap())
} else {
Msg::FetchFail
}
});
let request = Request::get("http://localhost:8081/load")
.body(Nothing)
.unwrap();
let task = yew::services::FetchService::fetch(request, callback).unwrap();
self.ft = Some(task)
}
Msg::FetchSuccess(data) => {
self.value = data;
self.ft = None
}
Msg::FetchFail => {
ConsoleService::log("Fetching of data failed!!!");
self.ft = None
}
Msg::AddOne => {
self.value += 1;
ConsoleService::log("Increment")
}
Msg::SubtractOne => {
self.value -= 1;
ConsoleService::log("Decrement")
}
Msg::SetValue => {
let current = self.value.to_string();
let input = DialogService::prompt("Set value to?", Some(current.as_str()))
.unwrap()
.parse::<i64>();
match input {
Ok(value) => {
if value == self.value {
return false;
}
let msg = format!("Do you want to change the value to {}?", value);
let confirmed = DialogService::confirm(msg.as_str());
if confirmed {
let msg = format!("Changed {} to {}.", self.value, value);
self.value.update(value);
DialogService::alert(msg.as_str());
ConsoleService::log(msg.as_str())
} else {
DialogService::alert("Did not change value.")
}
}
Err(_) => ConsoleService::log("Can not parse number"),
}
}
}
self.storage.store(KEY, Json(&self.value));
true
}
fn change(&mut self, _props: Self::Properties) -> ShouldRender {
false
}
fn view(&self) -> Html {
html! {
<div>
<h1>{ self.value }</h1>
<button onclick=self.link.callback(|_| Msg::AddOne)>{ "+1" }</button>
<button onclick=self.link.callback(|_| Msg::SubtractOne)>{ "-1" }</button>
<button onclick=self.link.callback(|_| Msg::SetValue)>{ "Set value" }</button>
<button onclick=self.link.callback(|_| Msg::FetchStart)>{ "Load" }</button>
<button onclick=self.link.callback(|_| Msg::SendStart)>{ "Save" }</button>
</div>
}
}
}
#[wasm_bindgen(start)]
pub fn run_app() {
yew::start_app::<Model>();
}