1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#![recursion_limit="1024"]
mod coapws;
mod binentry;
mod message_editor;
mod messageexchanger;
mod colorserver;
mod colorpicker;
mod about;
mod coapwsmessage;
mod util;
use wasm_bindgen::prelude::*;
use yew::prelude::*;
use yew_router::{prelude::*, Switch};
#[derive(Clone)]
struct FragmentOnlyRoute<I: Switch> {
pub inner: I,
}
impl<I: Switch> Switch for FragmentOnlyRoute<I> {
fn from_route_part<STATE>(part: String, state: Option<STATE>) -> (Option<Self>, Option<STATE>) {
let part = match part.find('#') {
Some(i) => &part[i..],
None => "",
}.to_string();
let (slef, outstate) = I::from_route_part(part, state);
(slef.map(|s| s.into()), outstate)
}
fn build_route_section<STATE>(self, route: &mut String) -> Option<STATE> {
self.inner.build_route_section(route)
}
}
impl<I: Switch> From<I> for FragmentOnlyRoute<I> {
fn from(inner: I) -> Self {
Self { inner }
}
}
struct Tabbing {
link: ComponentLink<Self>,
router: Box<dyn Bridge<RouteAgent>>,
}
impl Component for Tabbing {
type Message = Msg;
type Properties = ();
fn create(_: Self::Properties, link: ComponentLink<Self>) -> Self {
let callback = link.callback(|_| Msg::NoOp);
let router = RouteAgent::bridge(callback);
Self { link, router }
}
fn update(&mut self, msg: Self::Message) -> ShouldRender {
match msg {
Msg::ColorServerChange { ep, rd } => {
let route = Route::from(TabRoute::ColorServer { ep, rd });
self.router.send(yew_router::agent::RouteRequest::ChangeRoute(route));
}
Msg::NoOp => {}
}
false
}
fn change(&mut self, _: Self::Properties) -> ShouldRender {
false
}
fn view(&self) -> Html {
let colorserver_onchange = self.link.callback(|(ep, rd)| Msg::ColorServerChange { ep, rd });
html! { <>
<nav>
<ul>
<li><RouterAnchor<TabRoute> route=TabRoute::MessageExchanger>{ "Message exchanger" } </RouterAnchor<TabRoute>></li>
<li><RouterAnchor<TabRoute> route=TabRoute::ColorServer { ep: "-".to_string(), rd: "-".to_string()}> { "Color server" } </RouterAnchor<TabRoute>></li>
<li><RouterAnchor<TabRoute> route=TabRoute::ColorPicker> { "Color client" } </RouterAnchor<TabRoute>></li>
<li><RouterAnchor<TabRoute> route=TabRoute::About> { "About Verdigris" } </RouterAnchor<TabRoute>></li>
</ul>
</nav>
<Router<FragmentOnlyRoute<TabRoute>>
render=Router::render(move |switch: FragmentOnlyRoute<TabRoute>| {
match switch.inner {
TabRoute::MessageExchanger => html! { <messageexchanger::CoAPWSMessageExchanger /> },
TabRoute::ColorServer { ep, rd } => html! {
<colorserver::ColorServer
ep=match ep.as_str() { "-" => None, x => Some(ep) }
rd=match rd.as_str() { "-" => None, x => Some(rd) }
onchange=&colorserver_onchange
/>
},
TabRoute::ColorPicker => html! { <colorpicker::ColorPicker /> },
TabRoute::About => html! { <about::About /> },
}})
redirect=Router::redirect(|route: Route| FragmentOnlyRoute::from(TabRoute::About))
/>
</> }
}
}
pub enum Msg {
ColorServerChange { ep: String, rd: String },
NoOp,
}
#[derive(Debug, Clone, Switch)]
pub enum TabRoute {
#[to = "#msgex"]
MessageExchanger,
#[to = "#colserv:{ep}:{*:rd}"]
ColorServer { ep: String, rd: String },
#[to = "#colcli"]
ColorPicker,
#[to = "#about"]
About,
}
#[wasm_bindgen(start)]
pub fn run_app() {
std::panic::set_hook(Box::new(console_error_panic_hook::hook));
console_log::init_with_level(log::Level::Debug)
.expect("Console not available for logging");
App::<Tabbing>::new().mount_to_body();
}