navigator init

This commit is contained in:
Jovi Hsu 2021-11-02 00:30:23 +08:00
parent 6c1ee72ace
commit 5b07e503e7
8 changed files with 250 additions and 5 deletions

View File

@ -4,7 +4,7 @@ authors = [
]
categories = ["wasm", "web-programming", "sslvpn"]
description = ""
edition = "2018"
edition = "2021"
keywords = ["yew", "wasm", "wasm-bindgen", "web", "sslvpn"]
license = "MIT"
name = "webgateway"
@ -19,6 +19,9 @@ crate-type = ["cdylib", "rlib"]
[dependencies]
wasm-bindgen = "^0.2"
yew = "0.18"
js-sys = "0.3.55"
web-sys = "0.3.55"
yew-router = "0.15"
# The `console_error_panic_hook` crate provides better debugging of panics by
# logging them with `console.error`. This is great for development, but requires
# all the `std::fmt` and `std::panicking` infrastructure, so isn't great for

View File

@ -1,4 +1,40 @@
use std::borrow::Cow;
use crate::pages::{page_home::PageHome, page_not_found::PageNotFound, page_ssh::PageSsh};
use yew::html::IntoPropValue;
use yew::prelude::*;
use yew::services::ConsoleService;
use yew::virtual_dom::VNode;
use yew::Component;
use yew_router::prelude::*;
use yew_router::{router::Router, Switch};
#[derive(Switch, Clone, Debug)]
enum AppRoute {
// #[at("/ssh/:id")]
// Ssh(i32),
#[to = "/ssh"]
Ssh,
#[to = "/!"]
Home,
#[to = ""]
NotFound,
}
impl Into<&str> for AppRoute {
fn into(self) -> &'static str {
match self {
AppRoute::Ssh => &"/ssh",
_ => &"/",
}
}
}
impl IntoPropValue<Option<Cow<'_, str>>> for AppRoute {
fn into_prop_value(self: AppRoute) -> Option<Cow<'static, str>> {
Some(Cow::Borrowed(self.into()))
}
}
pub struct App {}
@ -8,8 +44,8 @@ impl Component for App {
type Message = Msg;
type Properties = ();
fn create(_: Self::Properties, _: ComponentLink<Self>) -> Self {
App {}
fn create(_: Self::Properties, _link: ComponentLink<Self>) -> Self {
Self {}
}
fn update(&mut self, _msg: Self::Message) -> ShouldRender {
@ -20,9 +56,61 @@ impl Component for App {
false
}
fn view(&self) -> Html {
fn view(&self) -> VNode {
html! {
<p>{ "Hello world!\n\n\n\n" }</p>
<>
{ self.view_nav() }
<main class="content">
<Router<AppRoute>
render = Router::render(Self::switch)
redirect=Router::redirect(|route: Route| {
ConsoleService::log(&format!("{:?}", route));
AppRoute::NotFound
})
/>
</main>
<footer class="footer">
<div class="content has-text-centered">
{ "Powered by " }
<a href="https://yew.rs">{ "Yew" }</a>
</div>
</footer>
</>
}
}
}
impl App {
fn view_nav(&self) -> Html {
html! {
<nav class="navbar" role="navigation" aria-label="main navigation">
<div class=classes!("navbar-menu")>
<RouterAnchor<AppRoute> classes="navbar-item" route=AppRoute::Home>
{ "Home" }
</RouterAnchor<AppRoute>>
<RouterAnchor<AppRoute> classes="navbar-item" route=AppRoute::Ssh>
{ "Ssh" }
</RouterAnchor<AppRoute>>
</div>
</nav>
}
}
fn switch(switch: AppRoute) -> Html {
ConsoleService::log(&format!("{:?}", switch));
match switch {
// Route::Ssh(ip) => {
// html! { <Ssh /> }
// }
AppRoute::Ssh => {
html! {<PageSsh />}
}
AppRoute::Home => {
html! {<PageHome />}
}
AppRoute::NotFound => {
html! { <PageNotFound /> }
}
}
}
}

View File

@ -1,7 +1,10 @@
mod app;
mod utils;
mod pages;
use wasm_bindgen::prelude::*;
use wasm_bindgen::JsCast;
use web_sys::{console, KeyboardEvent};
#[cfg(feature = "wee_alloc")]
#[global_allocator]
@ -9,6 +12,20 @@ static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;
#[wasm_bindgen]
pub fn run_app() -> Result<(), JsValue> {
let window = web_sys::window().unwrap();
let handler_submit = move |e: KeyboardEvent| {
e.stop_propagation();
console::log_1(&format!("{:?}", e).into())
};
let handler = Box::new(handler_submit) as Box<dyn FnMut(_)>;
let cb = Closure::wrap(handler);
window
.add_event_listener_with_callback("keydown", cb.as_ref().unchecked_ref())
.unwrap();
cb.forget();
yew::start_app::<app::App>();
Ok(())

3
src/pages/mod.rs Normal file
View File

@ -0,0 +1,3 @@
pub mod page_home;
pub mod page_not_found;
pub mod page_ssh;

39
src/pages/page_home.rs Normal file
View File

@ -0,0 +1,39 @@
use yew::prelude::*;
use yew::Component;
use yew::ShouldRender;
pub struct PageHome;
impl Component for PageHome {
type Message = ();
type Properties = ();
fn create(_props: Self::Properties, _link: ComponentLink<Self>) -> Self {
Self
}
fn view(&self) -> Html {
html! {
<section class="hero is-danger is-bold is-large">
<div class="hero-body">
<div class="container">
<h1 class="title">
{ "Hello World" }
</h1>
<h2 class="subtitle">
{ "Hello again" }
</h2>
</div>
</div>
</section>
}
}
fn update(&mut self, _msg: Self::Message) -> ShouldRender {
true
}
fn change(&mut self, _props: Self::Properties) -> ShouldRender {
false
}
}

View File

@ -0,0 +1,39 @@
use yew::prelude::*;
use yew::Component;
use yew::ShouldRender;
pub struct PageNotFound;
impl Component for PageNotFound {
type Message = ();
type Properties = ();
fn create(_props: Self::Properties, _link: ComponentLink<Self>) -> Self {
Self
}
fn view(&self) -> Html {
html! {
<section class="hero is-danger is-bold is-large">
<div class="hero-body">
<div class="container">
<h1 class="title">
{ "Page not found" }
</h1>
<h2 class="subtitle">
{ "Page page does not seem to exist" }
</h2>
</div>
</div>
</section>
}
}
fn update(&mut self, _msg: Self::Message) -> ShouldRender {
false
}
fn change(&mut self, _props: Self::Properties) -> ShouldRender {
false
}
}

28
src/pages/page_ssh.rs Normal file
View File

@ -0,0 +1,28 @@
use yew::prelude::*;
pub struct PageSsh {}
pub enum Msg {}
impl Component for PageSsh {
type Message = Msg;
type Properties = ();
fn create(_: Self::Properties, _: ComponentLink<Self>) -> Self {
PageSsh {}
}
fn update(&mut self, _msg: Self::Message) -> ShouldRender {
true
}
fn change(&mut self, _: Self::Properties) -> ShouldRender {
false
}
fn view(&self) -> Html {
html! {
<p>{ "Hello ssh!\n\n\n\n" }</p>
}
}
}

View File

@ -4,9 +4,37 @@
<head>
<meta charset="utf-8" />
<title>Hello, World</title>
<style type="text/css">
.navbar {
width: 100%;
height: 20px;
background-color: #66ccff;
}
.navbar .navbar-item {
margin: auto;
position: relative;
padding: 40px;
}
html,
body {
height: 100%;
margin: 0;
}
.content {
min-height: calc(100% - 58px - 40px);
}
.footer {
height: 58px;
}
</style>
<script src="./bootstrap.js" defer></script>
</head>
<body>
</body>
</html>