forked from projectmoon/tenebrous-dicebot
Web UI with a functional async-await boundary!
This commit is contained in:
parent
6154bf2c0b
commit
6eca450346
|
@ -14,3 +14,4 @@ bigboy
|
|||
.tmp*
|
||||
node_modules
|
||||
dist/
|
||||
yarn-error.log
|
||||
|
|
|
@ -3341,7 +3341,10 @@ name = "tenebrous-web-ui"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"grpc-web-client",
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
"web-sys",
|
||||
"yew",
|
||||
"yew-router",
|
||||
"yewdux",
|
||||
|
|
|
@ -15,7 +15,10 @@ yewtil = {version = "0.3" }
|
|||
yew-router = {version = "0.14" }
|
||||
yewdux = {version = "^0.6" }
|
||||
wasm-bindgen = { version = "0.2" }
|
||||
wasm-bindgen-futures = "0.4"
|
||||
js-sys = "0.3"
|
||||
grpc-web-client = "0.1"
|
||||
web-sys = "0.3"
|
||||
|
||||
# hopefully we can add grpc-web later instead of graphql.
|
||||
# prost = { version = "0.7.0", default-features = false }
|
||||
|
|
|
@ -1,98 +1,84 @@
|
|||
use oaths::OathsList;
|
||||
use rooms::RoomList;
|
||||
use wasm_bindgen::prelude::*;
|
||||
use yew::prelude::*;
|
||||
use yew_router::{components::RouterAnchor, prelude::*};
|
||||
|
||||
pub mod grpc;
|
||||
pub mod oaths;
|
||||
pub mod rooms;
|
||||
|
||||
#[derive(Switch, Clone, Debug)]
|
||||
pub enum AppRoute {
|
||||
#[to = "/oaths"]
|
||||
Oaths,
|
||||
#[to = "/commitments"]
|
||||
Commitments,
|
||||
#[to = "/studies"]
|
||||
Studies,
|
||||
#[to = "/divination"]
|
||||
RunicDivination,
|
||||
#[to = "/rooms"]
|
||||
Rooms,
|
||||
#[to = "/rooms/{room_id}"]
|
||||
Room(String),
|
||||
#[to = "/"]
|
||||
Index,
|
||||
}
|
||||
|
||||
type AppRouter = Router<AppRoute>;
|
||||
type AppAnchor = RouterAnchor<AppRoute>;
|
||||
type AppAnchor = RouterAnchor<AppRoute>; //For rendering clickable links.
|
||||
|
||||
fn render_route(switch: AppRoute) -> Html {
|
||||
match switch {
|
||||
AppRoute::Oaths => {
|
||||
AppRoute::Rooms => {
|
||||
html! {
|
||||
<OathsList />
|
||||
<RoomList />
|
||||
}
|
||||
}
|
||||
AppRoute::Commitments => {
|
||||
AppRoute::Room(room_id) => {
|
||||
html! {
|
||||
<div>{"This is the commitments page."}</div>
|
||||
}
|
||||
}
|
||||
AppRoute::Studies => {
|
||||
html! {
|
||||
<div>{"This is the studies page."}</div>
|
||||
}
|
||||
}
|
||||
AppRoute::RunicDivination => {
|
||||
html! {
|
||||
<div>{"This is the runic divination page."}</div>
|
||||
<div>{"This is the specifi roompage."}</div>
|
||||
}
|
||||
}
|
||||
AppRoute::Index => {
|
||||
html! {
|
||||
<div>{"This is the index."}</div>
|
||||
<RoomList />
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct AppMenu;
|
||||
// struct AppMenu;
|
||||
|
||||
impl Component for AppMenu {
|
||||
type Message = ();
|
||||
type Properties = ();
|
||||
// impl Component for AppMenu {
|
||||
// type Message = ();
|
||||
// type Properties = ();
|
||||
|
||||
fn create(_: Self::Properties, _link: ComponentLink<Self>) -> Self {
|
||||
Self
|
||||
}
|
||||
// fn create(_: Self::Properties, _link: ComponentLink<Self>) -> Self {
|
||||
// Self
|
||||
// }
|
||||
|
||||
fn update(&mut self, _msg: Self::Message) -> ShouldRender {
|
||||
false
|
||||
}
|
||||
// fn update(&mut self, _msg: Self::Message) -> ShouldRender {
|
||||
// false
|
||||
// }
|
||||
|
||||
fn change(&mut self, _: Self::Properties) -> ShouldRender {
|
||||
false
|
||||
}
|
||||
// fn change(&mut self, _: Self::Properties) -> ShouldRender {
|
||||
// false
|
||||
// }
|
||||
|
||||
fn view(&self) -> Html {
|
||||
html! {
|
||||
<ul>
|
||||
<li>
|
||||
<AppAnchor route=AppRoute::Index>{"Home"}</AppAnchor>
|
||||
</li>
|
||||
<li>
|
||||
<AppAnchor route=AppRoute::Oaths>{"Oaths"}</AppAnchor>
|
||||
</li>
|
||||
<li>
|
||||
<AppAnchor route=AppRoute::Commitments>{"Commitments"}</AppAnchor>
|
||||
</li>
|
||||
<li>
|
||||
<AppAnchor route=AppRoute::Studies>{"Studies"}</AppAnchor>
|
||||
</li>
|
||||
<li>
|
||||
<AppAnchor route=AppRoute::RunicDivination>{"Runic Divination"}</AppAnchor>
|
||||
</li>
|
||||
</ul>
|
||||
}
|
||||
}
|
||||
}
|
||||
// fn view(&self) -> Html {
|
||||
// html! {
|
||||
// <ul>
|
||||
// <li>
|
||||
// <AppAnchor route=AppRoute::Index>{"Home"}</AppAnchor>
|
||||
// </li>
|
||||
// <li>
|
||||
// <AppAnchor route=AppRoute::Oaths>{"Oaths"}</AppAnchor>
|
||||
// </li>
|
||||
// <li>
|
||||
// <AppAnchor route=AppRoute::Commitments>{"Commitments"}</AppAnchor>
|
||||
// </li>
|
||||
// <li>
|
||||
// <AppAnchor route=AppRoute::Studies>{"Studies"}</AppAnchor>
|
||||
// </li>
|
||||
// <li>
|
||||
// <AppAnchor route=AppRoute::RunicDivination>{"Runic Divination"}</AppAnchor>
|
||||
// </li>
|
||||
// </ul>
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
struct App;
|
||||
|
||||
|
@ -116,7 +102,6 @@ impl Component for App {
|
|||
html! {
|
||||
<div>
|
||||
{"Hello World"}
|
||||
<AppMenu />
|
||||
<AppRouter render=AppRouter::render(render_route) />
|
||||
</div>
|
||||
}
|
||||
|
|
|
@ -1,77 +0,0 @@
|
|||
use yew::prelude::*;
|
||||
use yewdux::prelude::*;
|
||||
use yewtil::NeqAssign;
|
||||
|
||||
struct Oaths;
|
||||
|
||||
#[derive(Clone)]
|
||||
struct Oath {
|
||||
title: String,
|
||||
content: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Clone)]
|
||||
pub(crate) struct OathState {
|
||||
oaths: Vec<Oath>,
|
||||
}
|
||||
|
||||
type OathDispatch = DispatchProps<BasicStore<OathState>>;
|
||||
|
||||
//Oaths list
|
||||
pub(crate) struct StatefulOathsList {
|
||||
dispatch: OathDispatch,
|
||||
}
|
||||
|
||||
pub(crate) type OathsList = WithDispatch<StatefulOathsList>;
|
||||
|
||||
fn view_oath(oath: &Oath) -> Html {
|
||||
html! {
|
||||
<div>
|
||||
<div>{oath.title.clone()}</div>
|
||||
<div>{oath.content.clone()}</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
impl Component for StatefulOathsList {
|
||||
type Message = ();
|
||||
type Properties = OathDispatch;
|
||||
|
||||
fn create(dispatch: Self::Properties, _link: ComponentLink<Self>) -> Self {
|
||||
Self { dispatch }
|
||||
}
|
||||
|
||||
fn update(&mut self, _msg: Self::Message) -> ShouldRender {
|
||||
false
|
||||
}
|
||||
|
||||
fn change(&mut self, dispatch: Self::Properties) -> ShouldRender {
|
||||
self.dispatch.neq_assign(dispatch)
|
||||
}
|
||||
|
||||
fn view(&self) -> Html {
|
||||
let add_oath = self.dispatch.reduce_callback(|s| {
|
||||
s.oaths.push(Oath {
|
||||
title: "yolo".to_string(),
|
||||
content: "nolo".to_string(),
|
||||
})
|
||||
});
|
||||
|
||||
html! {
|
||||
<div>
|
||||
<button onclick=add_oath>{ "Add Oath" }</button>
|
||||
<ul>
|
||||
{
|
||||
for self.dispatch.state().oaths.iter().map(|oath| {
|
||||
view_oath(oath)
|
||||
})
|
||||
}
|
||||
</ul>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//New oath form
|
||||
|
||||
//Edit oath
|
|
@ -0,0 +1,113 @@
|
|||
use std::sync::Arc;
|
||||
use wasm_bindgen::prelude::*;
|
||||
use wasm_bindgen::JsValue;
|
||||
use wasm_bindgen_futures::{future_to_promise, spawn_local};
|
||||
use web_sys::console;
|
||||
use yew::prelude::*;
|
||||
use yewdux::prelude::*;
|
||||
use yewtil::NeqAssign;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct Room {
|
||||
room_id: String,
|
||||
display_name: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Clone)]
|
||||
pub(crate) struct RoomListState {
|
||||
rooms: Vec<Room>,
|
||||
}
|
||||
|
||||
pub(crate) enum Action {
|
||||
AddRoom(Room),
|
||||
}
|
||||
|
||||
impl Reducer for RoomListState {
|
||||
type Action = Action;
|
||||
|
||||
fn new() -> Self {
|
||||
Self { rooms: vec![] }
|
||||
}
|
||||
|
||||
fn reduce(&mut self, action: Self::Action) -> bool {
|
||||
match action {
|
||||
Action::AddRoom(room) => {
|
||||
self.rooms.push(room.clone());
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type RoomListDispatch = DispatchProps<ReducerStore<RoomListState>>;
|
||||
|
||||
//Oaths list
|
||||
#[doc(hidden)]
|
||||
pub(crate) struct YewduxRoomList {
|
||||
dispatch: RoomListDispatch,
|
||||
link: ComponentLink<YewduxRoomList>,
|
||||
}
|
||||
|
||||
pub(crate) type RoomList = WithDispatch<YewduxRoomList>;
|
||||
|
||||
fn view_room(room: &Room) -> Html {
|
||||
html! {
|
||||
<div>
|
||||
<div>{room.room_id.clone()}</div>
|
||||
<div>{room.display_name.clone()}</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
async fn do_things(dispatch: &RoomListDispatch) {
|
||||
dispatch.send(Action::AddRoom(Room {
|
||||
room_id: "asdf".into(),
|
||||
display_name: "adslkjg".into(),
|
||||
}));
|
||||
}
|
||||
|
||||
impl Component for YewduxRoomList {
|
||||
type Message = ();
|
||||
type Properties = RoomListDispatch;
|
||||
|
||||
fn create(dispatch: Self::Properties, link: ComponentLink<Self>) -> Self {
|
||||
Self { dispatch, link }
|
||||
}
|
||||
|
||||
fn update(&mut self, _msg: Self::Message) -> ShouldRender {
|
||||
false
|
||||
}
|
||||
|
||||
fn change(&mut self, dispatch: Self::Properties) -> ShouldRender {
|
||||
self.dispatch.neq_assign(dispatch)
|
||||
}
|
||||
|
||||
fn view(&self) -> Html {
|
||||
let dispatch = Arc::new(self.dispatch.clone());
|
||||
|
||||
let the_future = self.link.callback(move |_| {
|
||||
let dispatch = dispatch.clone();
|
||||
|
||||
spawn_local(async move {
|
||||
do_things(&*dispatch).await;
|
||||
});
|
||||
});
|
||||
|
||||
html! {
|
||||
<div>
|
||||
<button onclick=the_future>{ "Add Room" }</button>
|
||||
<ul>
|
||||
{
|
||||
for self.dispatch.state().rooms.iter().map(|oath| {
|
||||
view_room(oath)
|
||||
})
|
||||
}
|
||||
</ul>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//New oath form
|
||||
|
||||
//Edit oath
|
Loading…
Reference in New Issue