From 0c799d9ccb876d716756299775e5e26cc0cb3424 Mon Sep 17 00:00:00 2001 From: Denis Kolodin Date: Mon, 12 Aug 2019 00:51:10 +0900 Subject: [PATCH 01/27] Use async blocks instead of closures --- src/server.rs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/server.rs b/src/server.rs index af4465f..9d5922d 100644 --- a/src/server.rs +++ b/src/server.rs @@ -75,16 +75,17 @@ pub async fn process_ws( // TODO Read router_rx and send Reactions to a connected client let map = throttle_map.clone(); - let outbound_get = (async move || -> Result<(), Error> { + let outbound_get = async move { while let Some(reaction) = router_rx.next().await { + log::trace!("Reaction: {:?}", reaction); let mut map = map.lock().map_err(|_| Error::CantLockThrottleMap)?; map.insert(reaction.overlay_id(), reaction); } Ok(()) - })(); + }; let map = Arc::downgrade(&throttle_map); - let outbound_send = (async move || -> Result<(), Error> { + let outbound_send = async move { let mut tx = tx.sink_compat(); let ms = settings.throttle_ms(); let mut interval = Interval::new(ms); @@ -104,9 +105,9 @@ pub async fn process_ws( } } Ok(()) - })(); + }; - let inbound = (async move || -> Result<(), Error> { + let inbound = async move { let mut rx = rx.compat(); while let Some(msg) = rx.next().await.transpose()? { let payload = msg.as_bytes(); @@ -114,7 +115,8 @@ pub async fn process_ws( log::debug!("Action: {:?}", action); } Ok(()) - })(); + }; + let (r1, r2, r3) = join!(inbound, outbound_get, outbound_send); r1.and(r2).and(r3) } From 205edee58ab2e12300be11cde7c3ac704e414b96 Mon Sep 17 00:00:00 2001 From: Denis Kolodin Date: Mon, 12 Aug 2019 00:58:05 +0900 Subject: [PATCH 02/27] Add build script to ui --- Cargo.toml | 7 +++---- ui/Cargo.lock | 50 ++++++++++++++++++++++++++++++++++++++++++++------ ui/Cargo.toml | 11 ++++++++++- ui/build.rs | 5 +++++ 4 files changed, 62 insertions(+), 11 deletions(-) create mode 100644 ui/build.rs diff --git a/Cargo.toml b/Cargo.toml index 0d30d37..ee14efb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,8 +3,8 @@ name = "facade" version = "0.1.0" authors = ["Denis Kolodin "] edition = "2018" -repository = "https://github.com/DenisKolodin/facade" -homepage = "https://github.com/DenisKolodin/facade" +repository = "https://github.com/yewstack/facade" +homepage = "https://github.com/yewstack/facade" documentation = "https://docs.rs/facade/" license = "MIT/Apache-2.0" readme = "README.md" @@ -17,6 +17,7 @@ config = "0.9.3" headers = "0.2.1" failure = "0.1.5" flate2 = "1.0.9" +futures-timer = "0.2.1" log = "0.4.6" mime_guess = "2.0.0-alpha.6" serde = { version = "1.0.94", features = ["derive"] } @@ -25,8 +26,6 @@ tar = "0.4.26" tokio = "0.1.22" warp = "0.1.16" -futures-timer = "0.2.1" - [dependencies.futures-legacy] package = "futures" version = "0.1.28" diff --git a/ui/Cargo.lock b/ui/Cargo.lock index 9d69da6..a485a20 100644 --- a/ui/Cargo.lock +++ b/ui/Cargo.lock @@ -111,11 +111,12 @@ dependencies = [ "facade-protocol 0.1.0", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "sass-rs 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", "web_logger 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "yew 0.9.0 (git+https://github.com/DenisKolodin/yew)", + "yew 0.9.0 (git+https://github.com/yewstack/yew)", ] [[package]] @@ -216,6 +217,19 @@ dependencies = [ "autocfg 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "num_cpus" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "pkg-config" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "proc-macro-hack" version = "0.5.8" @@ -265,6 +279,26 @@ name = "ryu" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "sass-rs" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "sass-sys 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "sass-sys" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "semver" version = "0.9.0" @@ -454,7 +488,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "yew" version = "0.9.0" -source = "git+https://github.com/DenisKolodin/yew#c9d5c70af07234bbd53483464cefe81f4d1164d8" +source = "git+https://github.com/yewstack/yew#202ea014cb06de3ceb36d94ba24efdd655a63d60" dependencies = [ "anymap 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", "bincode 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -469,13 +503,13 @@ dependencies = [ "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "stdweb 0.4.18 (registry+https://github.com/rust-lang/crates.io-index)", "wasm-bindgen 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", - "yew-macro 0.9.0 (git+https://github.com/DenisKolodin/yew)", + "yew-macro 0.9.0 (git+https://github.com/yewstack/yew)", ] [[package]] name = "yew-macro" version = "0.9.0" -source = "git+https://github.com/DenisKolodin/yew#c9d5c70af07234bbd53483464cefe81f4d1164d8" +source = "git+https://github.com/yewstack/yew#202ea014cb06de3ceb36d94ba24efdd655a63d60" dependencies = [ "autocfg 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "boolinator 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -514,6 +548,8 @@ dependencies = [ "checksum num-bigint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "57450397855d951f1a41305e54851b1a7b8f5d2e349543a02a2effe25459f718" "checksum num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09" "checksum num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32" +"checksum num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcef43580c035376c0705c42792c294b66974abbfd2789b511784023f71f3273" +"checksum pkg-config 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c1d2cfa5a714db3b5f24f0915e74fcdf91d09d496ba61329705dda7774d2af" "checksum proc-macro-hack 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)" = "982a35d1194084ba319d65c4a68d24ca28f5fdb5b8bc20899e4eef8641ea5178" "checksum proc-macro-nested 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "369a6ed065f249a159e06c45752c780bda2fb53c995718f9e484d08daa9eb42e" "checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" @@ -521,6 +557,8 @@ dependencies = [ "checksum rustc-demangle 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "a7f4dccf6f4891ebcc0c39f9b6eb1a83b9bf5d747cb439ec6fba4f3b977038af" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" "checksum ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c92464b447c0ee8c4fb3824ecc8383b81717b9f1e74ba2e72540aef7b9f82997" +"checksum sass-rs 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "cabcf7c6e55053f359911187ac401409aad2dc14338cae972dec266fee486abd" +"checksum sass-sys 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6e16ac97c2335bc367e2d675f54c1823558f1b19a6c67671d48b70e30ae22972" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" "checksum serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)" = "7fe5626ac617da2f2d9c48af5515a21d5a480dbd151e01bb1c355e26a3e68113" @@ -542,5 +580,5 @@ dependencies = [ "checksum wasm-bindgen-shared 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)" = "326c32126e1a157b6ced7400061a84ac5b11182b2cda6edad7314eb3ae9ac9fe" "checksum web_logger 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a78db9c2146b833ba825496c1851886be8221097df558903321d304c83d161a5" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" -"checksum yew 0.9.0 (git+https://github.com/DenisKolodin/yew)" = "" -"checksum yew-macro 0.9.0 (git+https://github.com/DenisKolodin/yew)" = "" +"checksum yew 0.9.0 (git+https://github.com/yewstack/yew)" = "" +"checksum yew-macro 0.9.0 (git+https://github.com/yewstack/yew)" = "" diff --git a/ui/Cargo.toml b/ui/Cargo.toml index ae967b0..baf86dd 100644 --- a/ui/Cargo.toml +++ b/ui/Cargo.toml @@ -3,6 +3,10 @@ name = "facade-ui" version = "0.1.0" authors = ["Denis Kolodin "] edition = "2018" +repository = "https://github.com/yewstack/facade" +homepage = "https://github.com/yewstack/facade" +documentation = "https://docs.rs/facade/" +license = "MIT/Apache-2.0" [dependencies] failure = "0.1.5" @@ -11,8 +15,13 @@ serde = "1.0.94" serde_derive = "1.0.94" serde_json = "1.0.40" web_logger = "0.1.0" -yew = { git = "https://github.com/DenisKolodin/yew" } +yew = { git = "https://github.com/yewstack/yew" } [dependencies.protocol] package = "facade-protocol" +version = "0.1.0" path = "../protocol" + +[build-dependencies] +failure = "0.1.5" +sass-rs = "0.2.2" diff --git a/ui/build.rs b/ui/build.rs new file mode 100644 index 0000000..1db8e35 --- /dev/null +++ b/ui/build.rs @@ -0,0 +1,5 @@ +use failure::Error; + +fn main() -> Result<(), Error> { + Ok(()) +} From 07efd96776399cdf3077e722000ecec8a36cd3c6 Mon Sep 17 00:00:00 2001 From: Denis Kolodin Date: Mon, 12 Aug 2019 02:53:37 +0900 Subject: [PATCH 03/27] Replace less with sass embedded compiler --- .gitignore | 1 + ui/build.rs | 6 ++ ui/static/index.html | 3 +- ui/static/styles.less | 229 ------------------------------------------ ui/styles/_reset.scss | 12 +++ ui/styles/styles.scss | 1 + 6 files changed, 21 insertions(+), 231 deletions(-) delete mode 100644 ui/static/styles.less create mode 100644 ui/styles/_reset.scss create mode 100644 ui/styles/styles.scss diff --git a/.gitignore b/.gitignore index 98e5fcf..6865a93 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ target **/*.rs.bk Cargo.lock +*.css diff --git a/ui/build.rs b/ui/build.rs index 1db8e35..a983f57 100644 --- a/ui/build.rs +++ b/ui/build.rs @@ -1,5 +1,11 @@ use failure::Error; +use sass_rs::{compile_file, Options, OutputStyle}; +use std::fs::File; +use std::io::prelude::*; fn main() -> Result<(), Error> { + let data = compile_file("./styles/styles.scss", Options::default()).unwrap(); + let mut file = File::create("./static/styles.css")?; + file.write_all(data.as_bytes())?; Ok(()) } diff --git a/ui/static/index.html b/ui/static/index.html index 3f90802..7b739c1 100644 --- a/ui/static/index.html +++ b/ui/static/index.html @@ -21,8 +21,7 @@ } }); - - + diff --git a/ui/static/styles.less b/ui/static/styles.less deleted file mode 100644 index 7ac8882..0000000 --- a/ui/static/styles.less +++ /dev/null @@ -1,229 +0,0 @@ -// TODO Move to theme.less -// https://coolors.co/46b1c9-84c0c6-9fb7b9-bcc1ba-f2e2d2 -// MAXIMUM BLUE -@color1: rgba(70, 177, 201, 1); -// DARK BLUE SKY -@color2: rgba(132, 192, 198, 1); -// CAMBRIDGE BLUE -@color3: rgba(159, 183, 185, 1); -// GRAY (X11 GRAY) -@color4: rgba(188, 193, 186, 1); -// CHAMPANGE PINK -@color5: rgba(242, 226, 210, 1); - - -@import url('https://fonts.googleapis.com/css?family=Lato:300,400,700,900&display=swap'); -/*@font: BlinkMacSystemFont, -apple-system, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", "Helvetica", "Arial", sans-serif;*/ -@font: "Lato", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", "Helvetica", "Arial", sans-serif; - -/** { font-family: @font; font-size: 20px; }*/ -* { padding: 0; margin: 0; box-sizing: border-box; } - -.flex { display: flex; } -.flex-row { flex-direction: row; } -.flex-col { flex-direction: column; } -.pad { padding: 10px; } - -.fill { height: 100%; width: 100%; } -.horizontal { .flex; .flex-row; } -.vertical { .flex; .flex-col; } -.grow { flex-grow: 1; } -.stretch { align-items: stretch; } -.middle { align-items: center; } -.stick-corners { justify-content: space-between; } -.center { justify-content: center; } - -/* -.rows { .flex-row; .pad; } -.row { .pad; } -.columns { .flex-col; .pad; } -.column { .pad; } -*/ - -html { - .fill; - font-size: 16px; -} -body { - .fill; - font-family: @font; - background: #F9FAFB; - color: #495057; - font-size: 16px; - font-weight: 400; -} - -ul { - list-style: none; -} - -.spinner { - .flex; - .fill; - .middle; - .center; -} - - -.dashboard { - .fill; - .horizontal; - background: #f9f9fc; - color: #646c9a; - - .sidebar { - .vertical; - width: 220px; - background-color: #1e1e2d; - color: #fff; - - .header { - .horizontal; - .middle; - height: 3rem; - padding: 0.1rem 1rem; - background-color: #1a1a27; - border-bottom: 1px solid #ffff0014; - margin-bottom: 1.2rem; - .title { - font-size: 1.1rem; - font-weight: 700; - text-transform: uppercase; - } - } - .menu { - .vertical; - .item { - cursor:pointer; - padding: 10px 30px; - - &:hover, &.selected { - background-color: #1a1a27; - } - } - } - } - - .content { - .grow; - .vertical; - - .page { - .vertical; - .fill; - .header { - .horizontal; - .middle; - height: 3rem; - padding: 0.1rem 1rem; - border-bottom: 1px solid #e7e7e7; - .title { - font-size: 1rem; - font-weight: 400; - color: #434349; - } - .separator { - margin: 0.2rem 1rem 0 1rem; - width: 1px; - height: 1.5rem; - background: #e7e7e7; - } - .subtitle { - font-size: 0.8rem; - font-weight: 400; - color: #959cb6; - } - } - .body { - .grow; - background: #f2f3f8; - padding: 1rem; - } - } - } -} - -.container { - .grow; - .horizontal; - .panel { - .grow; - .vertical; - background-color: #fff; - border-radius: 4px; - box-shadow: 0 0 13px 0 rgba(82,63,105,.05); - margin: 0.5rem; - .panel-header { - .horizontal; - .middle; - height: 3rem; - padding: 0.1rem 1rem; - border-bottom: 1px solid #e7e7e7; - .panel-header-title { - font-size: 1rem; - font-weight: 400; - color: #48465b; - } - } - .panel-content { - .vertical; - .grow; - padding: 1rem; - } - } -} - -.list { - .list-item { - .horizontal; - .stick-corners; - .middle; - border-bottom: 1px dashed #ebedf2; - padding: 1rem 0; - &:last-child { border-bottom: none; } - .list-item-info { - .vertical; - .list-item-info-title { - font-size: 1.1rem; - font-weight: 500; - color: #595d6e; - margin-bottom: 0.5rem; - } - .list-item-info-description { - font-size: 1rem; - font-weight: 400; - color: #74788d; - } - } - .list-item-value { - font-size: 1.2rem; - font-weight: 600; - color: #5d78ff; - margin-left: 2rem; - } - } -} - -.panel .list-item:first-child { padding-top: 0; } -.panel .list-item:last-child { padding-bottom: 0; } - -.dynamic { - margin: 0 0.2rem; -} - -.fixed { - margin: 0 0.2rem; -} - -.layout { -} - -.layout-column { - .vertical; - .stretch; -} - -.layout-row { - .horizontal; - .stretch; -} diff --git a/ui/styles/_reset.scss b/ui/styles/_reset.scss new file mode 100644 index 0000000..f1a7dc3 --- /dev/null +++ b/ui/styles/_reset.scss @@ -0,0 +1,12 @@ +html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, pre, a, abbr, acronym, +address, big, cite, del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, +tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, +tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed, figure, figcaption, +footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video { + margin: 0; + padding: 0; + border: 0; + font-size: 100%; + font: inherit; + vertical-align: baseline; +} diff --git a/ui/styles/styles.scss b/ui/styles/styles.scss new file mode 100644 index 0000000..059c56e --- /dev/null +++ b/ui/styles/styles.scss @@ -0,0 +1 @@ +@import 'reset'; From 41b2e97b38d737692d9d414fca2bf8d73362bf4a Mon Sep 17 00:00:00 2001 From: Denis Kolodin Date: Mon, 12 Aug 2019 02:59:14 +0900 Subject: [PATCH 04/27] Use Compact format for SASS --- ui/build.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ui/build.rs b/ui/build.rs index a983f57..6efdd19 100644 --- a/ui/build.rs +++ b/ui/build.rs @@ -1,10 +1,12 @@ -use failure::Error; +use failure::{err_msg, Error}; use sass_rs::{compile_file, Options, OutputStyle}; use std::fs::File; use std::io::prelude::*; fn main() -> Result<(), Error> { - let data = compile_file("./styles/styles.scss", Options::default()).unwrap(); + let mut opts = Options::default(); + opts.output_style = OutputStyle::Compact; + let data = compile_file("./styles/styles.scss", opts).map_err(err_msg)?; let mut file = File::create("./static/styles.css")?; file.write_all(data.as_bytes())?; Ok(()) From 86f0a4c9c39e94d1444b38c99a4171c8b8ac02bb Mon Sep 17 00:00:00 2001 From: Denis Kolodin Date: Mon, 12 Aug 2019 17:36:32 +0900 Subject: [PATCH 05/27] Add block rule --- ui/styles/_reset.scss | 12 ------------ ui/styles/styles.scss | 31 ++++++++++++++++++++++++++++++- 2 files changed, 30 insertions(+), 13 deletions(-) delete mode 100644 ui/styles/_reset.scss diff --git a/ui/styles/_reset.scss b/ui/styles/_reset.scss deleted file mode 100644 index f1a7dc3..0000000 --- a/ui/styles/_reset.scss +++ /dev/null @@ -1,12 +0,0 @@ -html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, pre, a, abbr, acronym, -address, big, cite, del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, -tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, -tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed, figure, figcaption, -footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video { - margin: 0; - padding: 0; - border: 0; - font-size: 100%; - font: inherit; - vertical-align: baseline; -} diff --git a/ui/styles/styles.scss b/ui/styles/styles.scss index 059c56e..7f37294 100644 --- a/ui/styles/styles.scss +++ b/ui/styles/styles.scss @@ -1 +1,30 @@ -@import 'reset'; +@import url('https://fonts.googleapis.com/css?family=Nunito:300,400,600,700&display=swap'); + +// PALLETE + +// COLORS + +$background_color: #FFF; +$text_color: #000; +$small_padding: 30px; + +// MIXINS + +// Standard block that has no special properties +@mixin block { + margin: 0; + padding: 0; + border: 0; + font: inherit; + font-size: 100%; + vertical-align: baseline; +} + +html, body, div { + @include block; +} + +body { + background: $background_color; + color: $text_color; +} From cbbd51a003deaeb89d1ed80b1aaa80c0cbab9b58 Mon Sep 17 00:00:00 2001 From: Denis Kolodin Date: Mon, 12 Aug 2019 18:24:48 +0900 Subject: [PATCH 06/27] Remove current widgets system --- protocol/src/dashboard.rs | 15 ------- protocol/src/lib.rs | 95 +-------------------------------------- src/lib.rs | 2 +- src/router.rs | 2 +- ui/src/lib.rs | 2 +- ui/src/live.rs | 2 +- ui/src/widgets/mod.rs | 8 ++-- ui/styles/styles.scss | 15 +++++++ 8 files changed, 26 insertions(+), 115 deletions(-) delete mode 100644 protocol/src/dashboard.rs diff --git a/protocol/src/dashboard.rs b/protocol/src/dashboard.rs deleted file mode 100644 index a6f1d00..0000000 --- a/protocol/src/dashboard.rs +++ /dev/null @@ -1,15 +0,0 @@ -use super::{Layout, Value}; -use serde::{Deserialize, Serialize}; - -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct Dashboard { - pub title: Value, - pub pages: Vec, -} - -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct Page { - pub title: Value, - pub subtitle: Value, - pub body: Layout, -} diff --git a/protocol/src/lib.rs b/protocol/src/lib.rs index 4848d1b..d42750d 100644 --- a/protocol/src/lib.rs +++ b/protocol/src/lib.rs @@ -1,5 +1,3 @@ -pub mod dashboard; - use bigdecimal::BigDecimal; use failure::Fail; use serde::{Deserialize, Serialize}; @@ -48,6 +46,8 @@ pub enum Reaction { Delta(Delta), } +pub type Scene = (); + impl Message for Reaction {} pub type OverlayId = Option; @@ -61,103 +61,12 @@ impl Reaction { } } -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub enum Scene { - Spinner, - FullScreen(Layout), - Dashboard(dashboard::Dashboard), -} - -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct Footer { - pub copyright: Value, - pub menu: Menu, -} - -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct Menu { - pub items: Vec, -} - -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct MenuItem { - pub caption: Value, -} - -/// Like `Layout`, but has physical appearance -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub enum Container { - Blank, - Tabs(Vec), - Panel(Panel), -} - -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct Panel { - pub title: Option, - pub body: Layout, -} - -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct Tab { - title: Value, - body: Layout, -} - -/// Like `Container`, but without physical appearance (row, column, center) -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub enum Layout { - Blank, - Welcome, - Bind(Bind), - Control(Control), - Row(Vec), - Column(Vec), - List(List), - Container(Box), -} - -impl From for Layout { - fn from(bind: Bind) -> Self { - Self::Bind(bind) - } -} - -impl From for Layout { - fn from(control: Control) -> Self { - Self::Control(control) - } -} - -impl From for Layout { - fn from(container: Container) -> Self { - Self::Container(Box::new(container)) - } -} - -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct List { - pub items: Vec, -} - -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct ListItem { - pub title: Value, - pub description: Value, - pub bind: Bind, -} - #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub enum Bind { Dynamic(Id), Fixed(Value), } -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub enum Control { - Button(Id), -} - #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct Delta { pub id: Id, diff --git a/src/lib.rs b/src/lib.rs index 10359a2..2d58b44 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,7 @@ #![feature(async_await, async_closure)] mod control; -pub mod dsl; +//pub mod dsl; mod router; mod server; mod settings; diff --git a/src/router.rs b/src/router.rs index 2a0c997..de35454 100644 --- a/src/router.rs +++ b/src/router.rs @@ -55,7 +55,7 @@ pub type Response = Reaction; pub async fn main(mut receiver: Receiver) -> Result<(), Error> { let mut subscribers = Vec::new(); let mut board = HashMap::::new(); - let mut scene = Scene::Spinner; + let mut scene = (); // TODO: Scene::Spinner; while let Some(request) = receiver.rx.next().await { let mut drain_all = false; match request { diff --git a/ui/src/lib.rs b/ui/src/lib.rs index 29d24a6..14f0d28 100644 --- a/ui/src/lib.rs +++ b/ui/src/lib.rs @@ -22,7 +22,7 @@ impl Component for Model { impl Renderable for Model { fn view(&self) -> Html { html! { - + } } } diff --git a/ui/src/live.rs b/ui/src/live.rs index d125ccc..c6a77b0 100644 --- a/ui/src/live.rs +++ b/ui/src/live.rs @@ -71,7 +71,7 @@ impl Agent for LiveAgent { connection, subscriptions: HashMap::new(), listeners: HashMap::new(), - scene: Scene::Spinner, + scene: (),// TODO: Scene::Spinner, board: HashMap::new(), } } diff --git a/ui/src/widgets/mod.rs b/ui/src/widgets/mod.rs index f377d8c..ed2dde5 100644 --- a/ui/src/widgets/mod.rs +++ b/ui/src/widgets/mod.rs @@ -1,5 +1,6 @@ //! This module defines aliases to widget types. +/* mod bind; pub use bind::BindWidget as Bind; @@ -39,11 +40,12 @@ pub use panel::PanelWidget as Panel; mod scene; pub use scene::SceneWidget as Scene; -mod spinner; -pub use spinner::SpinnerWidget as Spinner; - mod welcome; pub use welcome::WelcomeWidget as Welcome; +*/ + +mod spinner; +pub use spinner::SpinnerWidget as Spinner; mod widget; pub use widget::{Reqs, View, Widget, WidgetModel}; diff --git a/ui/styles/styles.scss b/ui/styles/styles.scss index 7f37294..f4deb90 100644 --- a/ui/styles/styles.scss +++ b/ui/styles/styles.scss @@ -28,3 +28,18 @@ body { background: $background_color; color: $text_color; } + +// Master block +.container { + // TODO: Fluid +} + +// Alignment and justification +.layout { + // TODO: row column +} + +// Support breakpoints +.flex { + // TODO: breakpoints... +} From 7ff30d69853dcfafe511c9709e1d809029fd9d91 Mon Sep 17 00:00:00 2001 From: Denis Kolodin Date: Mon, 12 Aug 2019 22:38:10 +0900 Subject: [PATCH 07/27] Add Grid layout to the protocol --- protocol/src/lib.rs | 98 +++++++++++++++++++++++++++++++++++++++++---- src/router.rs | 2 +- ui/src/live.rs | 2 +- 3 files changed, 92 insertions(+), 10 deletions(-) diff --git a/protocol/src/lib.rs b/protocol/src/lib.rs index d42750d..6a43e7a 100644 --- a/protocol/src/lib.rs +++ b/protocol/src/lib.rs @@ -1,9 +1,9 @@ use bigdecimal::BigDecimal; use failure::Fail; use serde::{Deserialize, Serialize}; +use std::collections::HashMap; use std::fmt; - #[derive(Fail, Debug)] pub enum Error { #[fail(display = "serialization error: {}", _0)] @@ -16,7 +16,7 @@ impl From for Error { } } -pub trait Message: Serialize + for <'de> Deserialize<'de> + Sized { +pub trait Message: Serialize + for<'de> Deserialize<'de> + Sized { fn serialize(&self) -> Result, Error> { serde_json::to_vec(self).map_err(Error::from) } @@ -26,8 +26,7 @@ pub trait Message: Serialize + for <'de> Deserialize<'de> + Sized { } } - -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] pub struct Action { id: Id, kind: Kind, @@ -35,21 +34,104 @@ pub struct Action { impl Message for Action {} -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] pub enum Kind { Click, } -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] pub enum Reaction { Scene(Scene), Delta(Delta), } -pub type Scene = (); - impl Message for Reaction {} +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] +pub enum Scene { + Spinner, + App, + Container(Container), +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] +pub struct Container { + layout: Layout, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] +pub struct Layout { + flex_vec: Vec, + wrap: bool, + fill: bool, + reverse: bool, + direction: Option, + alignment: Option, + justify: Option, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash)] +pub enum Direction { + Row, + Column, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash)] +pub enum Align { + Start, + Center, + End, + SpaceAround, + SpaceBetween, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash)] +pub enum Justify { + Start, + Center, + End, + SpaceAround, + SpaceBetween, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] +pub struct Flex { + breakpoints: HashMap, + offsets: HashMap, + components: Vec, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub enum Breakpoint { + XSmall, + Small, + Medium, + Large, + XLarge, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub enum Cols { + N1, + N2, + N3, + N4, + N5, + N6, + N7, + N8, + N9, + N10, + N11, + N12, +} + +// TODO: Consider to replace with trait (but has issues with derived traits) +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] +pub enum Component { + List, +} + pub type OverlayId = Option; impl Reaction { diff --git a/src/router.rs b/src/router.rs index de35454..2a0c997 100644 --- a/src/router.rs +++ b/src/router.rs @@ -55,7 +55,7 @@ pub type Response = Reaction; pub async fn main(mut receiver: Receiver) -> Result<(), Error> { let mut subscribers = Vec::new(); let mut board = HashMap::::new(); - let mut scene = (); // TODO: Scene::Spinner; + let mut scene = Scene::Spinner; while let Some(request) = receiver.rx.next().await { let mut drain_all = false; match request { diff --git a/ui/src/live.rs b/ui/src/live.rs index c6a77b0..d125ccc 100644 --- a/ui/src/live.rs +++ b/ui/src/live.rs @@ -71,7 +71,7 @@ impl Agent for LiveAgent { connection, subscriptions: HashMap::new(), listeners: HashMap::new(), - scene: (),// TODO: Scene::Spinner, + scene: Scene::Spinner, board: HashMap::new(), } } From e3a886c2381a8b1f9f12480e24376291c98f41a3 Mon Sep 17 00:00:00 2001 From: Denis Kolodin Date: Mon, 12 Aug 2019 23:19:38 +0900 Subject: [PATCH 08/27] Implement Scene widget --- src/lib.rs | 1 + ui/src/lib.rs | 2 +- ui/src/widgets/container.rs | 21 +++------------------ ui/src/widgets/mod.rs | 12 ++++++------ ui/src/widgets/scene.rs | 11 +++++------ 5 files changed, 16 insertions(+), 31 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 2d58b44..9ea528d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -13,6 +13,7 @@ use futures::compat::Compat; use futures::{join, TryFutureExt}; use settings::Settings; use std::thread; +pub use protocol as dsl; pub fn main() -> Result { let settings = Settings::parse()?; diff --git a/ui/src/lib.rs b/ui/src/lib.rs index 14f0d28..29d24a6 100644 --- a/ui/src/lib.rs +++ b/ui/src/lib.rs @@ -22,7 +22,7 @@ impl Component for Model { impl Renderable for Model { fn view(&self) -> Html { html! { - + } } } diff --git a/ui/src/widgets/container.rs b/ui/src/widgets/container.rs index d09c53c..2430ec7 100644 --- a/ui/src/widgets/container.rs +++ b/ui/src/widgets/container.rs @@ -30,24 +30,9 @@ impl Widget for Model { } fn main_view(&self) -> View { - match self.container { - Container::Blank => { - html! { -

{ "Blank" }

- } - } - Container::Tabs(_) => { - html! { -

{ "Tabs" }

- } - } - Container::Panel(ref panel) => { - html! { -
- -
- } - } + html! { +
+
} } } diff --git a/ui/src/widgets/mod.rs b/ui/src/widgets/mod.rs index ed2dde5..77f222b 100644 --- a/ui/src/widgets/mod.rs +++ b/ui/src/widgets/mod.rs @@ -10,9 +10,6 @@ pub use blank::BlankWidget as Blank; mod button; pub use button::ButtonWidget as Button; -mod container; -pub use container::ContainerWidget as Container; - mod control; pub use control::ControlWidget as Control; @@ -37,13 +34,16 @@ pub use page::PageWidget as Page; mod panel; pub use panel::PanelWidget as Panel; -mod scene; -pub use scene::SceneWidget as Scene; - mod welcome; pub use welcome::WelcomeWidget as Welcome; */ +mod container; +pub use container::ContainerWidget as Container; + +mod scene; +pub use scene::SceneWidget as Scene; + mod spinner; pub use spinner::SpinnerWidget as Spinner; diff --git a/ui/src/widgets/scene.rs b/ui/src/widgets/scene.rs index 6f63515..855b1a7 100644 --- a/ui/src/widgets/scene.rs +++ b/ui/src/widgets/scene.rs @@ -1,6 +1,6 @@ use crate::live::{Requirement, ResponseEvt}; use crate::widgets::{self, Reqs, View, Widget, WidgetModel}; -use protocol::{Reaction, Scene}; +use protocol::{Container, Reaction, Scene}; use yew::{html, Properties, ShouldRender}; pub type SceneWidget = WidgetModel; @@ -45,16 +45,15 @@ impl Widget for Model { } } - Scene::FullScreen(ref layout) => { + Scene::App => { html! { -
- +
} } - Scene::Dashboard(ref dashboard) => { + Scene::Container(ref container) => { html! { - + } } } From 7dfd51e74a0ec47a5a014bb3798fd9069008e56d Mon Sep 17 00:00:00 2001 From: Denis Kolodin Date: Tue, 13 Aug 2019 07:36:07 +0900 Subject: [PATCH 09/27] Add Layout widget implementation with classes --- protocol/src/lib.rs | 23 +++++------ src/lib.rs | 2 +- ui/src/lib.rs | 1 + ui/src/utils.rs | 38 ++++++++++++++++++ ui/src/widgets/container.rs | 7 +++- ui/src/widgets/layout.rs | 77 ++++++++++--------------------------- ui/src/widgets/mod.rs | 6 +-- 7 files changed, 82 insertions(+), 72 deletions(-) create mode 100644 ui/src/utils.rs diff --git a/protocol/src/lib.rs b/protocol/src/lib.rs index 6a43e7a..5fe06a8 100644 --- a/protocol/src/lib.rs +++ b/protocol/src/lib.rs @@ -56,18 +56,19 @@ pub enum Scene { #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] pub struct Container { - layout: Layout, + pub fluid: bool, + pub layout: Layout, } #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] pub struct Layout { - flex_vec: Vec, - wrap: bool, - fill: bool, - reverse: bool, - direction: Option, - alignment: Option, - justify: Option, + pub flex_vec: Vec, + pub wrap: bool, + pub fill: bool, + pub reverse: bool, + pub direction: Option, + pub align: Option, + pub justify: Option, } #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash)] @@ -96,9 +97,9 @@ pub enum Justify { #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] pub struct Flex { - breakpoints: HashMap, - offsets: HashMap, - components: Vec, + pub breakpoints: HashMap, + pub offsets: HashMap, + pub components: Vec, } #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] diff --git a/src/lib.rs b/src/lib.rs index 9ea528d..fcb9b30 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,9 +11,9 @@ use failure::Error; use futures::channel::mpsc; use futures::compat::Compat; use futures::{join, TryFutureExt}; +pub use protocol as dsl; use settings::Settings; use std::thread; -pub use protocol as dsl; pub fn main() -> Result { let settings = Settings::parse()?; diff --git a/ui/src/lib.rs b/ui/src/lib.rs index 29d24a6..7efe5e5 100644 --- a/ui/src/lib.rs +++ b/ui/src/lib.rs @@ -2,6 +2,7 @@ mod live; mod widgets; +mod utils; use yew::{html, Component, ComponentLink, Html, Renderable, ShouldRender}; diff --git a/ui/src/utils.rs b/ui/src/utils.rs new file mode 100644 index 0000000..c459cc8 --- /dev/null +++ b/ui/src/utils.rs @@ -0,0 +1,38 @@ +use protocol::{Align, Direction, Justify}; + +pub trait ToClass { + fn to_class(&self) -> &'static str; +} + +impl ToClass for Align { + fn to_class(&self) -> &'static str { + match self { + Align::Start => "align-start", + Align::Center => "align-center", + Align::End => "align-end", + Align::SpaceAround => "align-space-around", + Align::SpaceBetween => "align-space-between", + } + } +} + +impl ToClass for Direction { + fn to_class(&self) -> &'static str { + match self { + Direction::Row => "row", + Direction::Column => "column", + } + } +} + +impl ToClass for Justify { + fn to_class(&self) -> &'static str { + match self { + Justify::Start => "justify-start", + Justify::Center => "justify-center", + Justify::End => "justify-end", + Justify::SpaceAround => "justify-space-around", + Justify::SpaceBetween => "justify-space-between", + } + } +} diff --git a/ui/src/widgets/container.rs b/ui/src/widgets/container.rs index 2430ec7..1b90f7a 100644 --- a/ui/src/widgets/container.rs +++ b/ui/src/widgets/container.rs @@ -30,8 +30,13 @@ impl Widget for Model { } fn main_view(&self) -> View { + let mut classes = vec!["container"]; + if self.container.fluid { + classes.push("fluid"); + } html! { -
+
+
} } diff --git a/ui/src/widgets/layout.rs b/ui/src/widgets/layout.rs index 05e114c..1ee68e6 100644 --- a/ui/src/widgets/layout.rs +++ b/ui/src/widgets/layout.rs @@ -1,4 +1,5 @@ use crate::widgets::{self, Reqs, View, Widget, WidgetModel}; +use crate::utils::ToClass; use protocol::Layout; use yew::{html, Properties}; @@ -30,65 +31,29 @@ impl Widget for Model { } fn main_view(&self) -> View { - match self.layout { - Layout::Blank => { - html! { -

{ "Blank" }

- } - } - Layout::Welcome => { - html! { -

{ "Welcome" }

- } - } - Layout::Bind(ref bind) => { - html! { - - } - } - Layout::Control(ref control) => { - html! { - - } - } - Layout::Row(ref layouts) => { - html! { -
- { for layouts.iter().map(|lyo| self.row(lyo)) } -
- } - } - Layout::Column(ref layouts) => { - html! { -
- { for layouts.iter().map(|lyo| self.column(lyo)) } -
- } - } - Layout::List(ref list) => { - html! { - - } - } - Layout::Container(ref container) => { - html! { - - } - } + let mut classes = Vec::with_capacity(10); + classes.push("layout"); + if self.layout.wrap { + classes.push("wrap"); } - } -} - -impl Model { - fn column(&self, layout: &Layout) -> View { - html! { - + if self.layout.fill { + classes.push("fill"); + } + if self.layout.reverse { + classes.push("reverse"); + } + if let Some(ref direction) = self.layout.direction { + classes.push(direction.to_class()); + } + if let Some(ref align) = self.layout.align { + classes.push(align.to_class()); + } + if let Some(ref justify) = self.layout.justify { + classes.push(justify.to_class()); } - } - - fn row(&self, layout: &Layout) -> View { html! { - +
+
} } } diff --git a/ui/src/widgets/mod.rs b/ui/src/widgets/mod.rs index 77f222b..7b4e158 100644 --- a/ui/src/widgets/mod.rs +++ b/ui/src/widgets/mod.rs @@ -22,9 +22,6 @@ pub use dynamic::DynamicWidget as Dynamic; mod fixed; pub use fixed::FixedWidget as Fixed; -mod layout; -pub use layout::LayoutWidget as Layout; - mod list; pub use list::ListWidget as List; @@ -38,6 +35,9 @@ mod welcome; pub use welcome::WelcomeWidget as Welcome; */ +mod layout; +pub use layout::LayoutWidget as Layout; + mod container; pub use container::ContainerWidget as Container; From 6524f58f9825a6bdba83ca07c21d036d0a02210e Mon Sep 17 00:00:00 2001 From: Denis Kolodin Date: Tue, 13 Aug 2019 07:47:06 +0900 Subject: [PATCH 10/27] Add DSL for containers --- src/dsl.rs | 35 +++++++++++++++++++++++++++++++++++ src/lib.rs | 3 +-- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/src/dsl.rs b/src/dsl.rs index 0539366..7ba0a7f 100644 --- a/src/dsl.rs +++ b/src/dsl.rs @@ -1,5 +1,39 @@ #![allow(non_snake_case)] +use std::collections::HashMap; + +pub fn Scene(container: protocol::Container) -> protocol::Scene { + protocol::Scene::Container(container) +} + +pub fn Container(layout: protocol::Layout) -> protocol::Container { + protocol::Container { + layout, + fluid: false, + } +} + +pub fn Layout(flex_vec: Vec) -> protocol::Layout { + protocol::Layout { + flex_vec, + wrap: false, + fill: false, + reverse: false, + direction: None, + align: None, + justify: None, + } +} + +pub fn Flex() -> protocol::Flex { + protocol::Flex { + breakpoints: HashMap::new(), + offsets: HashMap::new(), + components: Vec::new(), + } +} + +/* use protocol::{self, Id, Layout, Value}; // ╔═╗┌─┐┌─┐┌┐┌┌─┐┌─┐ @@ -136,3 +170,4 @@ pub mod macros { } } pub use super::many; +*/ diff --git a/src/lib.rs b/src/lib.rs index fcb9b30..10359a2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,7 @@ #![feature(async_await, async_closure)] mod control; -//pub mod dsl; +pub mod dsl; mod router; mod server; mod settings; @@ -11,7 +11,6 @@ use failure::Error; use futures::channel::mpsc; use futures::compat::Compat; use futures::{join, TryFutureExt}; -pub use protocol as dsl; use settings::Settings; use std::thread; From 3e01ec0261285f31dcc39c7195f580bd755cbf6c Mon Sep 17 00:00:00 2001 From: Denis Kolodin Date: Tue, 13 Aug 2019 07:58:48 +0900 Subject: [PATCH 11/27] Add view_flex method to layout --- ui/src/widgets/layout.rs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/ui/src/widgets/layout.rs b/ui/src/widgets/layout.rs index 1ee68e6..6f88925 100644 --- a/ui/src/widgets/layout.rs +++ b/ui/src/widgets/layout.rs @@ -1,6 +1,6 @@ use crate::widgets::{self, Reqs, View, Widget, WidgetModel}; use crate::utils::ToClass; -use protocol::Layout; +use protocol::{Flex, Layout}; use yew::{html, Properties}; pub type LayoutWidget = WidgetModel; @@ -53,7 +53,21 @@ impl Widget for Model { } html! {
+ { for self.layout.flex_vec.iter().map(|flex| self.view_flex(flex)) }
} } } + +impl Model { + fn view_flex(&self, flex: &Flex) -> View { + html! { + let mut classes = Vec::with_capacity(10); + classes.push("flex"); + html! { +
+
+ } + } + } +} From c082e53da2486a69fec9059f01f8b866bf9f79d6 Mon Sep 17 00:00:00 2001 From: Denis Kolodin Date: Thu, 15 Aug 2019 01:07:48 +0900 Subject: [PATCH 12/27] Add a minimal grid --- protocol/Cargo.toml | 2 ++ protocol/src/lib.rs | 7 ++++-- ui/Cargo.lock | 36 +++++++++++++++++++++++++++ ui/Cargo.toml | 2 ++ ui/build.rs | 2 +- ui/src/lib.rs | 2 +- ui/src/utils.rs | 54 ++++++++++++++++++++++++++++++++++++---- ui/src/widgets/layout.rs | 2 +- ui/styles/_vars.scss | 13 ++++++++++ ui/styles/styles.sass | 50 +++++++++++++++++++++++++++++++++++++ ui/styles/styles.scss | 45 --------------------------------- 11 files changed, 160 insertions(+), 55 deletions(-) create mode 100644 ui/styles/_vars.scss create mode 100644 ui/styles/styles.sass delete mode 100644 ui/styles/styles.scss diff --git a/protocol/Cargo.toml b/protocol/Cargo.toml index 096cb47..e92c28d 100644 --- a/protocol/Cargo.toml +++ b/protocol/Cargo.toml @@ -17,3 +17,5 @@ bigdecimal = { version = "0.1.0", features = ["serde"] } failure = "0.1.5" serde = { version = "1.0.94", features = ["derive"] } serde_json = "1.0.40" +strum = "0.15.0" +strum_macros = "0.15.0" diff --git a/protocol/src/lib.rs b/protocol/src/lib.rs index 5fe06a8..c415ad8 100644 --- a/protocol/src/lib.rs +++ b/protocol/src/lib.rs @@ -3,6 +3,7 @@ use failure::Fail; use serde::{Deserialize, Serialize}; use std::collections::HashMap; use std::fmt; +use strum_macros::EnumIter; #[derive(Fail, Debug)] pub enum Error { @@ -102,7 +103,9 @@ pub struct Flex { pub components: Vec, } -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub type FlexWidth = (Breakpoint, Cols); + +#[derive(Serialize, Deserialize, EnumIter, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub enum Breakpoint { XSmall, Small, @@ -111,7 +114,7 @@ pub enum Breakpoint { XLarge, } -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[derive(Serialize, Deserialize, EnumIter, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub enum Cols { N1, N2, diff --git a/ui/Cargo.lock b/ui/Cargo.lock index a485a20..675868d 100644 --- a/ui/Cargo.lock +++ b/ui/Cargo.lock @@ -102,6 +102,8 @@ dependencies = [ "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "strum 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", + "strum_macros 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -110,6 +112,7 @@ version = "0.1.0" dependencies = [ "facade-protocol 0.1.0", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "sass-rs 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", @@ -144,6 +147,14 @@ name = "fnv" version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "heck" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-segmentation 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "http" version = "0.1.18" @@ -397,6 +408,22 @@ name = "stdweb-internal-runtime" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "strum" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "strum_macros" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "syn" version = "0.15.44" @@ -418,6 +445,11 @@ dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "unicode-segmentation" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "unicode-xid" version = "0.1.0" @@ -538,6 +570,7 @@ dependencies = [ "checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" "checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" +"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" "checksum http 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "372bcb56f939e449117fb0869c2e8fd8753a8223d92a172c6e808cf123a5b6e4" "checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d" "checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08" @@ -570,8 +603,11 @@ dependencies = [ "checksum stdweb-derive 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0e21ebd9179de08f2300a65454268a17ea3de204627458588c84319c4def3930" "checksum stdweb-internal-macros 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "e68f7d08b76979a43e93fe043b66d2626e35d41d68b0b85519202c6dd8ac59fa" "checksum stdweb-internal-runtime 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d52317523542cc0af5b7e31017ad0f7d1e78da50455e38d5657cd17754f617da" +"checksum strum 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e5d1c33039533f051704951680f1adfd468fd37ac46816ded0d9ee068e60f05f" +"checksum strum_macros 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "47cd23f5c7dee395a00fa20135e2ec0fffcdfa151c56182966d7a3261343432e" "checksum syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)" = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" "checksum synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "02353edf96d6e4dc81aea2d8490a7e9db177bf8acb0e951c24940bf866cb313f" +"checksum unicode-segmentation 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1967f4cdfc355b37fd76d2a954fb2ed3871034eb4f26d60537d88795cfc332a9" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum wasm-bindgen 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)" = "ffde3534e5fa6fd936e3260cd62cd644b8656320e369388f9303c955895e35d4" "checksum wasm-bindgen-backend 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)" = "40c0543374a7ae881cdc5d32d19de28d1d1929e92263ffa7e31712cc2d53f9f1" diff --git a/ui/Cargo.toml b/ui/Cargo.toml index baf86dd..d818f05 100644 --- a/ui/Cargo.toml +++ b/ui/Cargo.toml @@ -10,7 +10,9 @@ license = "MIT/Apache-2.0" [dependencies] failure = "0.1.5" +lazy_static = "1.3.0" log = "0.4.6" +#phf = { version = "0.7.24", features = ["macros"] } serde = "1.0.94" serde_derive = "1.0.94" serde_json = "1.0.40" diff --git a/ui/build.rs b/ui/build.rs index 6efdd19..17f4694 100644 --- a/ui/build.rs +++ b/ui/build.rs @@ -6,7 +6,7 @@ use std::io::prelude::*; fn main() -> Result<(), Error> { let mut opts = Options::default(); opts.output_style = OutputStyle::Compact; - let data = compile_file("./styles/styles.scss", opts).map_err(err_msg)?; + let data = compile_file("./styles/styles.sass", opts).map_err(err_msg)?; let mut file = File::create("./static/styles.css")?; file.write_all(data.as_bytes())?; Ok(()) diff --git a/ui/src/lib.rs b/ui/src/lib.rs index 7efe5e5..4261826 100644 --- a/ui/src/lib.rs +++ b/ui/src/lib.rs @@ -1,8 +1,8 @@ #![recursion_limit = "128"] mod live; -mod widgets; mod utils; +mod widgets; use yew::{html, Component, ComponentLink, Html, Renderable, ShouldRender}; diff --git a/ui/src/utils.rs b/ui/src/utils.rs index c459cc8..096655f 100644 --- a/ui/src/utils.rs +++ b/ui/src/utils.rs @@ -1,11 +1,13 @@ -use protocol::{Align, Direction, Justify}; +use lazy_static::lazy_static; +use protocol::{Align, Direction, FlexWidth, Justify}; +use std::collections::HashMap; pub trait ToClass { - fn to_class(&self) -> &'static str; + fn to_class(&self) -> &str; } impl ToClass for Align { - fn to_class(&self) -> &'static str { + fn to_class(&self) -> &str { match self { Align::Start => "align-start", Align::Center => "align-center", @@ -17,7 +19,7 @@ impl ToClass for Align { } impl ToClass for Direction { - fn to_class(&self) -> &'static str { + fn to_class(&self) -> &str { match self { Direction::Row => "row", Direction::Column => "column", @@ -26,7 +28,7 @@ impl ToClass for Direction { } impl ToClass for Justify { - fn to_class(&self) -> &'static str { + fn to_class(&self) -> &str { match self { Justify::Start => "justify-start", Justify::Center => "justify-center", @@ -36,3 +38,45 @@ impl ToClass for Justify { } } } + +lazy_static! { + // TODO: Use phf crate here? + static ref FLEX_WIDTH: HashMap = { + use protocol::Breakpoint::*; + use protocol::Cols::*; + let mut map = HashMap::new(); + let brks = [ + (XSmall, "xs"), + (Small, "sm"), + (Medium, "md"), + (Large, "la"), + (XLarge, "xl"), + ]; + let cols = [ + (N1, "1"), + (N2, "2"), + (N3, "3"), + (N4, "4"), + (N5, "5"), + (N6, "6"), + (N7, "7"), + (N8, "8"), + (N9, "9"), + (N10, "10"), + (N11, "11"), + (N12, "12"), + ]; + for (brk, brk_cls) in &brks { + for (col, col_cls) in &cols { + map.insert((brk.to_owned(), col.to_owned()), format!("{}-{}", brk_cls, col_cls)); + } + } + map + }; +} + +impl ToClass for FlexWidth { + fn to_class(&self) -> &str { + FLEX_WIDTH.get(self).unwrap() + } +} diff --git a/ui/src/widgets/layout.rs b/ui/src/widgets/layout.rs index 6f88925..ec17688 100644 --- a/ui/src/widgets/layout.rs +++ b/ui/src/widgets/layout.rs @@ -1,5 +1,5 @@ -use crate::widgets::{self, Reqs, View, Widget, WidgetModel}; use crate::utils::ToClass; +use crate::widgets::{self, Reqs, View, Widget, WidgetModel}; use protocol::{Flex, Layout}; use yew::{html, Properties}; diff --git a/ui/styles/_vars.scss b/ui/styles/_vars.scss new file mode 100644 index 0000000..c20fd40 --- /dev/null +++ b/ui/styles/_vars.scss @@ -0,0 +1,13 @@ +$spacer: 4px !default; + +$form-gutter: $spacer * 2 !default; + +$grid-columns: 12 !default; +$grid-gutter: $spacer * 6 !default; +$grid-breakpoints: ( + 'xs': 0, + 'sm': 600px, + 'md': 960px, + 'lg': 1280px - 16px, + 'xl': 1920px - 16px +) !default; diff --git a/ui/styles/styles.sass b/ui/styles/styles.sass new file mode 100644 index 0000000..a0540d8 --- /dev/null +++ b/ui/styles/styles.sass @@ -0,0 +1,50 @@ +@import './_vars'; + +@import url('https://fonts.googleapis.com/css?family=Nunito:300,400,600,700&display=swap'); + +// VARS + +// PALLETE + +// COLORS + +$background_color: #FFF +$text_color: #000 +$small_padding: 30px + +// MIXINS + +// Standard block that has no special properties +=block + margin: 0 + padding: 0 + border: 0 + font: inherit + font-size: 100% + vertical-align: baseline + +html, body, div + +block + +body + background: $background_color + color: $text_color + +// Master block +.container + width: 100% + padding: 0 + margin-right: auto + margin-left: auto + +// Alignment and justification +.layout + display: flex + flex-wrap: wrap + flex: 1 1 auto + margin-right: -$grid-gutter / 2 + margin-left: -$grid-gutter / 2 + +// Support breakpoints +.flex + // TODO: breakpoints... diff --git a/ui/styles/styles.scss b/ui/styles/styles.scss deleted file mode 100644 index f4deb90..0000000 --- a/ui/styles/styles.scss +++ /dev/null @@ -1,45 +0,0 @@ -@import url('https://fonts.googleapis.com/css?family=Nunito:300,400,600,700&display=swap'); - -// PALLETE - -// COLORS - -$background_color: #FFF; -$text_color: #000; -$small_padding: 30px; - -// MIXINS - -// Standard block that has no special properties -@mixin block { - margin: 0; - padding: 0; - border: 0; - font: inherit; - font-size: 100%; - vertical-align: baseline; -} - -html, body, div { - @include block; -} - -body { - background: $background_color; - color: $text_color; -} - -// Master block -.container { - // TODO: Fluid -} - -// Alignment and justification -.layout { - // TODO: row column -} - -// Support breakpoints -.flex { - // TODO: breakpoints... -} From 1add4fb950b8a6fa833d67b330c424e770799436 Mon Sep 17 00:00:00 2001 From: Denis Kolodin Date: Thu, 15 Aug 2019 07:22:16 +0900 Subject: [PATCH 13/27] Add baseline example --- Cargo.toml | 8 +++++++- examples/baseline/main.rs | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 examples/baseline/main.rs diff --git a/Cargo.toml b/Cargo.toml index ee14efb..21e8bb7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,7 +32,7 @@ version = "0.1.28" [dependencies.futures] package = "futures-preview" -version = "0.3.0-alpha.17" +version = "=0.3.0-alpha.17" features = ["async-await", "nightly", "compat"] [dependencies.protocol] @@ -43,6 +43,12 @@ path = "protocol" [build-dependencies] failure = "0.1.5" +[dev-dependencies] +env_logger = "0.6.2" +runtime = "0.3.0-alpha.6" +runtime-tokio = "0.3.0-alpha.5" +tokio-signal = "0.2.7" + [features] default = [] refresh = [] diff --git a/examples/baseline/main.rs b/examples/baseline/main.rs new file mode 100644 index 0000000..0e17b3a --- /dev/null +++ b/examples/baseline/main.rs @@ -0,0 +1,32 @@ +#![feature(async_await)] + +use failure::Error; +use futures::compat::Future01CompatExt; +use futures::future::select; +use futures::{FutureExt, StreamExt}; +use futures_legacy::{Future as _, Stream as _}; + +#[runtime::main(runtime_tokio::Tokio)] +pub async fn main() -> Result<(), Error> { + env_logger::try_init()?; + let ctrl_c = tokio_signal::ctrl_c() + .flatten_stream() + .into_future() + .compat(); + + let mut control = facade::main()?; + let scene = { + use facade::dsl::*; + Scene(Container( + Layout(vec![ + Flex(), + Flex(), + Flex(), + ]) + )) + }; + control.scene(scene); + + ctrl_c.await; + Ok(()) +} From 8bce60f564b7583fb666fc005cc8ab28f0ef2435 Mon Sep 17 00:00:00 2001 From: Denis Kolodin Date: Thu, 15 Aug 2019 22:11:23 +0900 Subject: [PATCH 14/27] Add app widget (empty) --- examples/baseline/main.rs | 14 ++++++++------ protocol/src/lib.rs | 37 ++++++++++++++++++++++++++++++++++++- src/dsl.rs | 17 +++++++++++++++-- ui/src/widgets/app.rs | 39 +++++++++++++++++++++++++++++++++++++++ ui/src/widgets/mod.rs | 3 +++ ui/src/widgets/scene.rs | 5 ++--- 6 files changed, 103 insertions(+), 12 deletions(-) create mode 100644 ui/src/widgets/app.rs diff --git a/examples/baseline/main.rs b/examples/baseline/main.rs index 0e17b3a..a2d16db 100644 --- a/examples/baseline/main.rs +++ b/examples/baseline/main.rs @@ -17,12 +17,14 @@ pub async fn main() -> Result<(), Error> { let mut control = facade::main()?; let scene = { use facade::dsl::*; - Scene(Container( - Layout(vec![ - Flex(), - Flex(), - Flex(), - ]) + Scene(App( + Container( + Layout(vec![ + Flex(), + Flex(), + Flex(), + ]) + ) )) }; control.scene(scene); diff --git a/protocol/src/lib.rs b/protocol/src/lib.rs index c415ad8..bda0288 100644 --- a/protocol/src/lib.rs +++ b/protocol/src/lib.rs @@ -51,10 +51,45 @@ impl Message for Reaction {} #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] pub enum Scene { Spinner, - App, + App(App), Container(Container), } +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] +pub struct App { + pub navigation_drawer: List, + pub app_bar: Bar, + pub content: Container, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] +pub struct List { + pub items: Vec, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] +pub struct ListItem { + pub action: Icon, + pub content: Title, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] +pub enum Icon { + Home, + MenuSandwich, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] +pub struct Title { + pub caption: String, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] +pub struct Bar { + pub nav_icon: Icon, + pub title: Title, +} + #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] pub struct Container { pub fluid: bool, diff --git a/src/dsl.rs b/src/dsl.rs index 7ba0a7f..c1109e8 100644 --- a/src/dsl.rs +++ b/src/dsl.rs @@ -2,8 +2,21 @@ use std::collections::HashMap; -pub fn Scene(container: protocol::Container) -> protocol::Scene { - protocol::Scene::Container(container) +pub fn Scene(app: protocol::App) -> protocol::Scene { + protocol::Scene::App(app) +} + +pub fn App(content: protocol::Container) -> protocol::App { + protocol::App { + navigation_drawer: protocol::List { items: Vec::new() }, + app_bar: protocol::Bar { + nav_icon: protocol::Icon::MenuSandwich, + title: protocol::Title { + caption: "Title".into(), + } + }, + content, + } } pub fn Container(layout: protocol::Layout) -> protocol::Container { diff --git a/ui/src/widgets/app.rs b/ui/src/widgets/app.rs new file mode 100644 index 0000000..b818f7c --- /dev/null +++ b/ui/src/widgets/app.rs @@ -0,0 +1,39 @@ +use crate::widgets::{self, Reqs, View, Widget, WidgetModel}; +use protocol::App; +use yew::{html, Properties}; + +pub type AppWidget = WidgetModel; + +pub struct Model { + app: App, +} + +#[derive(Properties, PartialEq, Clone)] +pub struct Props { + #[props(required)] + pub app: App, +} + +impl Widget for Model { + type Message = (); + type Properties = Props; + + fn produce(props: &Self::Properties) -> Self { + Self { + app: props.app.clone(), + } + } + + fn recompose(&mut self, props: &Self::Properties) -> Reqs { + self.app = props.app.clone(); + None + } + + fn main_view(&self) -> View { + let mut classes = vec!["app"]; + html! { +
+
+ } + } +} diff --git a/ui/src/widgets/mod.rs b/ui/src/widgets/mod.rs index 7b4e158..bd3cecf 100644 --- a/ui/src/widgets/mod.rs +++ b/ui/src/widgets/mod.rs @@ -35,6 +35,9 @@ mod welcome; pub use welcome::WelcomeWidget as Welcome; */ +mod app; +pub use app::AppWidget as App; + mod layout; pub use layout::LayoutWidget as Layout; diff --git a/ui/src/widgets/scene.rs b/ui/src/widgets/scene.rs index 855b1a7..814c9a1 100644 --- a/ui/src/widgets/scene.rs +++ b/ui/src/widgets/scene.rs @@ -45,10 +45,9 @@ impl Widget for Model { } } - Scene::App => { + Scene::App(ref app) => { html! { -
-
+ } } Scene::Container(ref container) => { From df492737dc25a65b2d0487e5759b700ae92d0272 Mon Sep 17 00:00:00 2001 From: Denis Kolodin Date: Thu, 15 Aug 2019 23:19:57 +0900 Subject: [PATCH 15/27] Add List and Icon --- examples/baseline/main.rs | 1 + src/dsl.rs | 10 ++++++++-- ui/src/widgets/app.rs | 1 + ui/src/widgets/icon.rs | 18 ++++++++++++++++++ ui/src/widgets/list.rs | 8 +++----- ui/src/widgets/mod.rs | 13 ++++++++----- 6 files changed, 39 insertions(+), 12 deletions(-) create mode 100644 ui/src/widgets/icon.rs diff --git a/examples/baseline/main.rs b/examples/baseline/main.rs index a2d16db..20359af 100644 --- a/examples/baseline/main.rs +++ b/examples/baseline/main.rs @@ -18,6 +18,7 @@ pub async fn main() -> Result<(), Error> { let scene = { use facade::dsl::*; Scene(App( + List(vec![]), Container( Layout(vec![ Flex(), diff --git a/src/dsl.rs b/src/dsl.rs index c1109e8..14d702c 100644 --- a/src/dsl.rs +++ b/src/dsl.rs @@ -6,9 +6,9 @@ pub fn Scene(app: protocol::App) -> protocol::Scene { protocol::Scene::App(app) } -pub fn App(content: protocol::Container) -> protocol::App { +pub fn App(list: protocol::List, content: protocol::Container) -> protocol::App { protocol::App { - navigation_drawer: protocol::List { items: Vec::new() }, + navigation_drawer: list, app_bar: protocol::Bar { nav_icon: protocol::Icon::MenuSandwich, title: protocol::Title { @@ -19,6 +19,12 @@ pub fn App(content: protocol::Container) -> protocol::App { } } +pub fn List(items: Vec) -> protocol::List { + protocol::List { + items, + } +} + pub fn Container(layout: protocol::Layout) -> protocol::Container { protocol::Container { layout, diff --git a/ui/src/widgets/app.rs b/ui/src/widgets/app.rs index b818f7c..9c82f2e 100644 --- a/ui/src/widgets/app.rs +++ b/ui/src/widgets/app.rs @@ -33,6 +33,7 @@ impl Widget for Model { let mut classes = vec!["app"]; html! {
+
} } diff --git a/ui/src/widgets/icon.rs b/ui/src/widgets/icon.rs new file mode 100644 index 0000000..dd41986 --- /dev/null +++ b/ui/src/widgets/icon.rs @@ -0,0 +1,18 @@ +use yew::html::Component; +use yew::{html, Html}; + +pub struct Icon { + icon: protocol::Icon, +} + +impl Icon { + pub fn new(icon: protocol::Icon) -> Self { + Self { icon } + } + + pub fn render(&self) -> Html { + html! { +

{ "Icon"}

+ } + } +} diff --git a/ui/src/widgets/list.rs b/ui/src/widgets/list.rs index 49d856f..c6af849 100644 --- a/ui/src/widgets/list.rs +++ b/ui/src/widgets/list.rs @@ -41,12 +41,10 @@ impl Model { fn view_item(&self, item: &protocol::ListItem) -> View { html! {
-
-
{ &item.title }
-
{ &item.description }
+
+ { widgets::Icon::new(item.action.clone()).render() }
-
- +
} diff --git a/ui/src/widgets/mod.rs b/ui/src/widgets/mod.rs index bd3cecf..5f722af 100644 --- a/ui/src/widgets/mod.rs +++ b/ui/src/widgets/mod.rs @@ -22,9 +22,6 @@ pub use dynamic::DynamicWidget as Dynamic; mod fixed; pub use fixed::FixedWidget as Fixed; -mod list; -pub use list::ListWidget as List; - mod page; pub use page::PageWidget as Page; @@ -38,11 +35,17 @@ pub use welcome::WelcomeWidget as Welcome; mod app; pub use app::AppWidget as App; +mod container; +pub use container::ContainerWidget as Container; + +mod icon; +pub use icon::Icon; + mod layout; pub use layout::LayoutWidget as Layout; -mod container; -pub use container::ContainerWidget as Container; +mod list; +pub use list::ListWidget as List; mod scene; pub use scene::SceneWidget as Scene; From c2221a155f60240a4c04f85f85744046cc11e589 Mon Sep 17 00:00:00 2001 From: Denis Kolodin Date: Fri, 16 Aug 2019 00:39:11 +0900 Subject: [PATCH 16/27] Render ListItem --- examples/baseline/main.rs | 4 +++- src/dsl.rs | 10 ++++++++++ ui/src/widgets/app.rs | 9 ++++++++- ui/src/widgets/list.rs | 1 + 4 files changed, 22 insertions(+), 2 deletions(-) diff --git a/examples/baseline/main.rs b/examples/baseline/main.rs index 20359af..d69f9c8 100644 --- a/examples/baseline/main.rs +++ b/examples/baseline/main.rs @@ -18,7 +18,9 @@ pub async fn main() -> Result<(), Error> { let scene = { use facade::dsl::*; Scene(App( - List(vec![]), + List(vec![ + ListItem(Icon::Home, "MenuItem".into()), + ]), Container( Layout(vec![ Flex(), diff --git a/src/dsl.rs b/src/dsl.rs index 14d702c..f3f3efb 100644 --- a/src/dsl.rs +++ b/src/dsl.rs @@ -1,5 +1,6 @@ #![allow(non_snake_case)] +pub use protocol::Icon; use std::collections::HashMap; pub fn Scene(app: protocol::App) -> protocol::Scene { @@ -25,6 +26,15 @@ pub fn List(items: Vec) -> protocol::List { } } +pub fn ListItem(icon: protocol::Icon, title: String) -> protocol::ListItem { + protocol::ListItem { + action: icon, + content: protocol::Title { + caption: title, + }, + } +} + pub fn Container(layout: protocol::Layout) -> protocol::Container { protocol::Container { layout, diff --git a/ui/src/widgets/app.rs b/ui/src/widgets/app.rs index 9c82f2e..482d2bd 100644 --- a/ui/src/widgets/app.rs +++ b/ui/src/widgets/app.rs @@ -33,7 +33,14 @@ impl Widget for Model { let mut classes = vec!["app"]; html! {
- + +
+
+
+ +
} } diff --git a/ui/src/widgets/list.rs b/ui/src/widgets/list.rs index c6af849..c6eb0fe 100644 --- a/ui/src/widgets/list.rs +++ b/ui/src/widgets/list.rs @@ -45,6 +45,7 @@ impl Model { { widgets::Icon::new(item.action.clone()).render() }
+ { &item.content.caption }
} From d1a4d4874f795248bb3f2b751294a211af57bcef Mon Sep 17 00:00:00 2001 From: Denis Kolodin Date: Sat, 17 Aug 2019 10:16:45 +0900 Subject: [PATCH 17/27] Add application layout --- protocol/src/lib.rs | 1 + src/dsl.rs | 1 + ui/src/widgets/app.rs | 22 +++++++++------- ui/src/widgets/list.rs | 6 ++++- ui/styles/styles.sass | 57 +++++++++++++++++++++++++++++++++++++----- 5 files changed, 71 insertions(+), 16 deletions(-) diff --git a/protocol/src/lib.rs b/protocol/src/lib.rs index bda0288..b56bea7 100644 --- a/protocol/src/lib.rs +++ b/protocol/src/lib.rs @@ -64,6 +64,7 @@ pub struct App { #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] pub struct List { + pub dense: bool, pub items: Vec, } diff --git a/src/dsl.rs b/src/dsl.rs index f3f3efb..37b4ea5 100644 --- a/src/dsl.rs +++ b/src/dsl.rs @@ -22,6 +22,7 @@ pub fn App(list: protocol::List, content: protocol::Container) -> protocol::App pub fn List(items: Vec) -> protocol::List { protocol::List { + dense: true, items, } } diff --git a/ui/src/widgets/app.rs b/ui/src/widgets/app.rs index 482d2bd..07965f2 100644 --- a/ui/src/widgets/app.rs +++ b/ui/src/widgets/app.rs @@ -30,16 +30,20 @@ impl Widget for Model { } fn main_view(&self) -> View { - let mut classes = vec!["app"]; html! { -
- -
-
-
- +
+
+
+
+
+ +
+
+
+
+
+ +
} diff --git a/ui/src/widgets/list.rs b/ui/src/widgets/list.rs index c6eb0fe..345204b 100644 --- a/ui/src/widgets/list.rs +++ b/ui/src/widgets/list.rs @@ -29,8 +29,12 @@ impl Widget for Model { } fn main_view(&self) -> View { + let mut classes = vec!["list"]; + if self.list.dense { + classes.push("dense"); + } html! { -
+
{ for self.list.items.iter().map(|item| self.view_item(item)) }
} diff --git a/ui/styles/styles.sass b/ui/styles/styles.sass index a0540d8..7f355b5 100644 --- a/ui/styles/styles.sass +++ b/ui/styles/styles.sass @@ -1,3 +1,11 @@ +// Ordering: +// 1. Position +// 2. Size +// 3. Layout +// 4. Margin +// 5. Padding +// 6. Other + @import './_vars'; @import url('https://fonts.googleapis.com/css?family=Nunito:300,400,600,700&display=swap'); @@ -30,21 +38,58 @@ body background: $background_color color: $text_color +a + cursor: pointer + // Master block .container width: 100% - padding: 0 margin-right: auto margin-left: auto + padding: 0 // Alignment and justification .layout - display: flex - flex-wrap: wrap - flex: 1 1 auto - margin-right: -$grid-gutter / 2 - margin-left: -$grid-gutter / 2 + display: flex + flex-wrap: wrap + flex: 1 1 auto + margin-right: -$grid-gutter / 2 + margin-left: -$grid-gutter / 2 // Support breakpoints .flex // TODO: breakpoints... + + +.f-application + display: flex + + &--wrap + position: relative + min-height: 100vh + max-width: 100% + display: flex + flex: 1 1 auto + flex-direction: column + backface-visibility: hidden + +.f-navigation-drawer + top: 0 + left: 0 + max-width: 100% + display: flex + flex-direction: column + overflow: hidden + pointer-events: auto + +.f-navigation-drawer__border + position: absolute + right: 0 + top: 0 + height: 100% + width: 1px + +.f-navigation-drawer__content + height: 100% + overflow-y: auto + overflow-x: hidden From 660ef662d4021a4e321e334f908e87da576ed240 Mon Sep 17 00:00:00 2001 From: Denis Kolodin Date: Sat, 17 Aug 2019 11:56:14 +0900 Subject: [PATCH 18/27] Add navigation bar to App layout --- ui/src/lib.rs | 2 +- ui/src/widgets/app.rs | 23 ++++++++++++++++----- ui/styles/styles.sass | 48 ++++++++++++++++++++++++------------------- 3 files changed, 46 insertions(+), 27 deletions(-) diff --git a/ui/src/lib.rs b/ui/src/lib.rs index 4261826..b616b07 100644 --- a/ui/src/lib.rs +++ b/ui/src/lib.rs @@ -1,4 +1,4 @@ -#![recursion_limit = "128"] +#![recursion_limit = "256"] mod live; mod utils; diff --git a/ui/src/widgets/app.rs b/ui/src/widgets/app.rs index 07965f2..8be3bb5 100644 --- a/ui/src/widgets/app.rs +++ b/ui/src/widgets/app.rs @@ -30,20 +30,33 @@ impl Widget for Model { } fn main_view(&self) -> View { + let mut drawer_style = String::new(); + drawer_style.push_str("height: 100vh;"); + drawer_style.push_str("top: 0px;"); + drawer_style.push_str("max-height: calc(100% - 36px);"); + drawer_style.push_str("transform: translateX(0%);"); + drawer_style.push_str("width: 256px;"); + let mut app_bar_style = String::new(); + app_bar_style.push_str("margin-top: 0px;"); + app_bar_style.push_str("transform: translateY(0px);"); + app_bar_style.push_str("left: 256px;"); + app_bar_style.push_str("right: 0px;"); html! {
-
-
-
+
+
+
-
+
-
+
+
} diff --git a/ui/styles/styles.sass b/ui/styles/styles.sass index 7f355b5..47cb091 100644 --- a/ui/styles/styles.sass +++ b/ui/styles/styles.sass @@ -20,6 +20,15 @@ $background_color: #FFF $text_color: #000 $small_padding: 30px +body + box-sizing: border-box + overflow-y: scroll + +* + box-sizing: inherit + padding: 0 + margin: 0 + // MIXINS // Standard block that has no special properties @@ -41,26 +50,6 @@ body a cursor: pointer -// Master block -.container - width: 100% - margin-right: auto - margin-left: auto - padding: 0 - -// Alignment and justification -.layout - display: flex - flex-wrap: wrap - flex: 1 1 auto - margin-right: -$grid-gutter / 2 - margin-left: -$grid-gutter / 2 - -// Support breakpoints -.flex - // TODO: breakpoints... - - .f-application display: flex @@ -69,8 +58,8 @@ a min-height: 100vh max-width: 100% display: flex - flex: 1 1 auto flex-direction: column + flex: 1 1 auto backface-visibility: hidden .f-navigation-drawer @@ -82,6 +71,11 @@ a overflow: hidden pointer-events: auto +.f-navigation-drawer--fixed + position: fixed + z-index: 6 + background: wheat + .f-navigation-drawer__border position: absolute right: 0 @@ -93,3 +87,15 @@ a height: 100% overflow-y: auto overflow-x: hidden + +.f-app-bar + background: yellow + +.f-toolbar + max-width: 100% + flex: 1 1 auto + +.f-content + display: flex + flex: 1 0 auto + max-width: 100% From 4401c45c07a38fffb6add3b4fcdcbb82283e4b7e Mon Sep 17 00:00:00 2001 From: Denis Kolodin Date: Sat, 17 Aug 2019 15:28:37 +0900 Subject: [PATCH 19/27] Move NavigationDrawer to a separate module --- examples/baseline/main.rs | 8 +++-- protocol/src/lib.rs | 7 ++++- src/dsl.rs | 10 ++++-- ui/src/widgets/app.rs | 13 +------- ui/src/widgets/mod.rs | 3 ++ ui/src/widgets/navigation_drawer.rs | 49 +++++++++++++++++++++++++++++ 6 files changed, 72 insertions(+), 18 deletions(-) create mode 100644 ui/src/widgets/navigation_drawer.rs diff --git a/examples/baseline/main.rs b/examples/baseline/main.rs index d69f9c8..34c372b 100644 --- a/examples/baseline/main.rs +++ b/examples/baseline/main.rs @@ -18,9 +18,11 @@ pub async fn main() -> Result<(), Error> { let scene = { use facade::dsl::*; Scene(App( - List(vec![ - ListItem(Icon::Home, "MenuItem".into()), - ]), + NavigationDrawer( + List(vec![ + ListItem(Icon::Home, "MenuItem".into()), + ]) + ), Container( Layout(vec![ Flex(), diff --git a/protocol/src/lib.rs b/protocol/src/lib.rs index b56bea7..f84e21a 100644 --- a/protocol/src/lib.rs +++ b/protocol/src/lib.rs @@ -57,11 +57,16 @@ pub enum Scene { #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] pub struct App { - pub navigation_drawer: List, + pub navigation_drawer: NavigationDrawer, pub app_bar: Bar, pub content: Container, } +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] +pub struct NavigationDrawer { + pub list: List, +} + #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] pub struct List { pub dense: bool, diff --git a/src/dsl.rs b/src/dsl.rs index 37b4ea5..8022557 100644 --- a/src/dsl.rs +++ b/src/dsl.rs @@ -7,9 +7,9 @@ pub fn Scene(app: protocol::App) -> protocol::Scene { protocol::Scene::App(app) } -pub fn App(list: protocol::List, content: protocol::Container) -> protocol::App { +pub fn App(navigation_drawer: protocol::NavigationDrawer, content: protocol::Container) -> protocol::App { protocol::App { - navigation_drawer: list, + navigation_drawer, app_bar: protocol::Bar { nav_icon: protocol::Icon::MenuSandwich, title: protocol::Title { @@ -20,6 +20,12 @@ pub fn App(list: protocol::List, content: protocol::Container) -> protocol::App } } +pub fn NavigationDrawer(list: protocol::List) -> protocol::NavigationDrawer { + protocol::NavigationDrawer { + list, + } +} + pub fn List(items: Vec) -> protocol::List { protocol::List { dense: true, diff --git a/ui/src/widgets/app.rs b/ui/src/widgets/app.rs index 8be3bb5..6bcc8c7 100644 --- a/ui/src/widgets/app.rs +++ b/ui/src/widgets/app.rs @@ -30,12 +30,6 @@ impl Widget for Model { } fn main_view(&self) -> View { - let mut drawer_style = String::new(); - drawer_style.push_str("height: 100vh;"); - drawer_style.push_str("top: 0px;"); - drawer_style.push_str("max-height: calc(100% - 36px);"); - drawer_style.push_str("transform: translateX(0%);"); - drawer_style.push_str("width: 256px;"); let mut app_bar_style = String::new(); app_bar_style.push_str("margin-top: 0px;"); app_bar_style.push_str("transform: translateY(0px);"); @@ -44,12 +38,7 @@ impl Widget for Model { html! {
-
-
- -
-
-
+
diff --git a/ui/src/widgets/mod.rs b/ui/src/widgets/mod.rs index 5f722af..386bf50 100644 --- a/ui/src/widgets/mod.rs +++ b/ui/src/widgets/mod.rs @@ -47,6 +47,9 @@ pub use layout::LayoutWidget as Layout; mod list; pub use list::ListWidget as List; +mod navigation_drawer; +pub use navigation_drawer::NavigationDrawerWidget as NavigationDrawer; + mod scene; pub use scene::SceneWidget as Scene; diff --git a/ui/src/widgets/navigation_drawer.rs b/ui/src/widgets/navigation_drawer.rs new file mode 100644 index 0000000..ddb63a7 --- /dev/null +++ b/ui/src/widgets/navigation_drawer.rs @@ -0,0 +1,49 @@ +use crate::widgets::{self, Reqs, View, Widget, WidgetModel}; +use yew::{html, Properties}; + +pub type NavigationDrawerWidget = WidgetModel; + +pub struct Model { + navigation_drawer: protocol::NavigationDrawer, +} + +#[derive(Properties, PartialEq, Clone)] +pub struct Props { + #[props(required)] + pub navigation_drawer: protocol::NavigationDrawer, +} + +impl Widget for Model { + type Message = (); + type Properties = Props; + + fn produce(props: &Self::Properties) -> Self { + Self { + navigation_drawer: props.navigation_drawer.clone(), + } + } + + fn recompose(&mut self, props: &Self::Properties) -> Reqs { + self.navigation_drawer = props.navigation_drawer.to_owned(); + None + } + + fn main_view(&self) -> View { + let mut classes = vec!["f-navigation-drawer"]; + classes.push("f-navigation-drawer--fixed"); + let mut drawer_style = String::new(); + drawer_style.push_str("height: 100vh;"); + drawer_style.push_str("top: 0px;"); + drawer_style.push_str("max-height: calc(100% - 36px);"); + drawer_style.push_str("transform: translateX(0%);"); + drawer_style.push_str("width: 256px;"); + html! { +
+
+ +
+
+
+ } + } +} From 354346496b6e9dc3ebea024f8d3e193e1504ed44 Mon Sep 17 00:00:00 2001 From: Denis Kolodin Date: Sat, 17 Aug 2019 16:06:02 +0900 Subject: [PATCH 20/27] Add styles for AppBar --- ui/src/widgets/app.rs | 6 +++++- ui/styles/_vars.scss | 3 +++ ui/styles/styles.sass | 12 ++++++++++++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/ui/src/widgets/app.rs b/ui/src/widgets/app.rs index 6bcc8c7..baf9ec6 100644 --- a/ui/src/widgets/app.rs +++ b/ui/src/widgets/app.rs @@ -39,7 +39,11 @@ impl Widget for Model {
-
+
+
+
+
{ &self.app.app_bar.title.caption }
+
diff --git a/ui/styles/_vars.scss b/ui/styles/_vars.scss index c20fd40..6493020 100644 --- a/ui/styles/_vars.scss +++ b/ui/styles/_vars.scss @@ -11,3 +11,6 @@ $grid-breakpoints: ( 'lg': 1280px - 16px, 'xl': 1920px - 16px ) !default; + +$toolbar-content-padding-y: 4px !default; +$toolbar-content-padding-x: 16px !default; diff --git a/ui/styles/styles.sass b/ui/styles/styles.sass index 47cb091..5d6ec03 100644 --- a/ui/styles/styles.sass +++ b/ui/styles/styles.sass @@ -91,10 +91,22 @@ a .f-app-bar background: yellow +.f-app-bar--fixed + position: fixed + top: 0 + z-index: 5 + .f-toolbar max-width: 100% flex: 1 1 auto +.f-toolbar__content + position: relative + align-items: center + display: flex + z-index: 0 + padding: $toolbar-content-padding-y $toolbar-content-padding-x + .f-content display: flex flex: 1 0 auto From 5752d1f35cecaf98c5370c6b07e33f185f811929 Mon Sep 17 00:00:00 2001 From: Denis Kolodin Date: Sat, 17 Aug 2019 17:01:46 +0900 Subject: [PATCH 21/27] Add Vuetify as a submodule --- .gitmodules | 3 + README.md | 6 + ui/src/widgets/app.rs | 16 +-- ui/src/widgets/navigation_drawer.rs | 8 +- ui/styles/_vars.scss | 16 --- ui/styles/styles.sass | 188 +++++++++++----------------- ui/styles/vuetify | 1 + 7 files changed, 97 insertions(+), 141 deletions(-) create mode 100644 .gitmodules delete mode 100644 ui/styles/_vars.scss create mode 160000 ui/styles/vuetify diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..ccae6ab --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "ui/styles/vuetify"] + path = ui/styles/vuetify + url = git@github.com:vuetifyjs/vuetify.git diff --git a/README.md b/README.md index 1dd9254..e0ed9cf 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,12 @@ To achieve that effect **Facade** uses [Yew](https://github.com/DenisKolodin/yew) framework to build a universal UI and use WebSocket connection to interact with your app that supply live updates to UI that renders them reactively. +## Vuetify relations + +We reuse CSS components' styles from Vuetify project: https://github.com/vuetifyjs/vuetify + +You can read the license of Vuetify here: https://github.com/vuetifyjs/vuetify/blob/master/LICENSE.md + ## Use-cases Uses-cases of this framework are unlimited and include but are not limited to the following cases diff --git a/ui/src/widgets/app.rs b/ui/src/widgets/app.rs index baf9ec6..2eddeb0 100644 --- a/ui/src/widgets/app.rs +++ b/ui/src/widgets/app.rs @@ -36,19 +36,19 @@ impl Widget for Model { app_bar_style.push_str("left: 256px;"); app_bar_style.push_str("right: 0px;"); html! { -
-
+
+
-
-
-
-
{ &self.app.app_bar.title.caption }
+
+
+
+
{ &self.app.app_bar.title.caption }
-
+
-
diff --git a/ui/src/widgets/navigation_drawer.rs b/ui/src/widgets/navigation_drawer.rs index ddb63a7..fa5a8ed 100644 --- a/ui/src/widgets/navigation_drawer.rs +++ b/ui/src/widgets/navigation_drawer.rs @@ -29,8 +29,8 @@ impl Widget for Model { } fn main_view(&self) -> View { - let mut classes = vec!["f-navigation-drawer"]; - classes.push("f-navigation-drawer--fixed"); + let mut classes = vec!["v-navigation-drawer"]; + classes.push("v-navigation-drawer--fixed"); let mut drawer_style = String::new(); drawer_style.push_str("height: 100vh;"); drawer_style.push_str("top: 0px;"); @@ -39,10 +39,10 @@ impl Widget for Model { drawer_style.push_str("width: 256px;"); html! {
-
+
-
+
} } diff --git a/ui/styles/_vars.scss b/ui/styles/_vars.scss deleted file mode 100644 index 6493020..0000000 --- a/ui/styles/_vars.scss +++ /dev/null @@ -1,16 +0,0 @@ -$spacer: 4px !default; - -$form-gutter: $spacer * 2 !default; - -$grid-columns: 12 !default; -$grid-gutter: $spacer * 6 !default; -$grid-breakpoints: ( - 'xs': 0, - 'sm': 600px, - 'md': 960px, - 'lg': 1280px - 16px, - 'xl': 1920px - 16px -) !default; - -$toolbar-content-padding-y: 4px !default; -$toolbar-content-padding-x: 16px !default; diff --git a/ui/styles/styles.sass b/ui/styles/styles.sass index 5d6ec03..e07c0b8 100644 --- a/ui/styles/styles.sass +++ b/ui/styles/styles.sass @@ -1,113 +1,75 @@ -// Ordering: -// 1. Position -// 2. Size -// 3. Layout -// 4. Margin -// 5. Padding -// 6. Other - -@import './_vars'; - -@import url('https://fonts.googleapis.com/css?family=Nunito:300,400,600,700&display=swap'); - -// VARS - -// PALLETE - -// COLORS - -$background_color: #FFF -$text_color: #000 -$small_padding: 30px - -body - box-sizing: border-box - overflow-y: scroll - -* - box-sizing: inherit - padding: 0 - margin: 0 - -// MIXINS - -// Standard block that has no special properties -=block - margin: 0 - padding: 0 - border: 0 - font: inherit - font-size: 100% - vertical-align: baseline - -html, body, div - +block - -body - background: $background_color - color: $text_color - -a - cursor: pointer - -.f-application - display: flex - - &--wrap - position: relative - min-height: 100vh - max-width: 100% - display: flex - flex-direction: column - flex: 1 1 auto - backface-visibility: hidden - -.f-navigation-drawer - top: 0 - left: 0 - max-width: 100% - display: flex - flex-direction: column - overflow: hidden - pointer-events: auto - -.f-navigation-drawer--fixed - position: fixed - z-index: 6 - background: wheat - -.f-navigation-drawer__border - position: absolute - right: 0 - top: 0 - height: 100% - width: 1px - -.f-navigation-drawer__content - height: 100% - overflow-y: auto - overflow-x: hidden - -.f-app-bar - background: yellow - -.f-app-bar--fixed - position: fixed - top: 0 - z-index: 5 - -.f-toolbar - max-width: 100% - flex: 1 1 auto - -.f-toolbar__content - position: relative - align-items: center - display: flex - z-index: 0 - padding: $toolbar-content-padding-y $toolbar-content-padding-x - -.f-content - display: flex - flex: 1 0 auto - max-width: 100% +@import './vuetify/packages/vuetify/src/styles/main.sass' +//@import './vuetify/packages/vuetify/src/components/VAlert/VAlert.sass' +@import './vuetify/packages/vuetify/src/components/VApp/VApp.sass' +@import './vuetify/packages/vuetify/src/components/VAppBar/VAppBar.sass' +//@import './vuetify/packages/vuetify/src/components/VAutocomplete/VAutocomplete.sass' +//@import './vuetify/packages/vuetify/src/components/VAvatar/VAvatar.sass' +//@import './vuetify/packages/vuetify/src/components/VBadge/VBadge.sass' +//@import './vuetify/packages/vuetify/src/components/VBanner/VBanner.sass' +//@import './vuetify/packages/vuetify/src/components/VBottomNavigation/VBottomNavigation.sass' +//@import './vuetify/packages/vuetify/src/components/VBottomSheet/VBottomSheet.sass' +//@import './vuetify/packages/vuetify/src/components/VBreadcrumbs/VBreadcrumbs.sass' +//@import './vuetify/packages/vuetify/src/components/VBtn/VBtn.sass' +//@import './vuetify/packages/vuetify/src/components/VBtnToggle/VBtnToggle.sass' +//@import './vuetify/packages/vuetify/src/components/VCalendar/VCalendar.sass' +//@import './vuetify/packages/vuetify/src/components/VCard/VCard.sass' +//@import './vuetify/packages/vuetify/src/components/VCarousel/VCarousel.sass' +//@import './vuetify/packages/vuetify/src/components/VCheckbox/VCheckbox.sass' +//@import './vuetify/packages/vuetify/src/components/VChip/VChip.sass' +//@import './vuetify/packages/vuetify/src/components/VChipGroup/VChipGroup.sass' +//@import './vuetify/packages/vuetify/src/components/VColorPicker/VColorPicker.sass' +//@import './vuetify/packages/vuetify/src/components/VCombobox/VCombobox.sass' +//@import './vuetify/packages/vuetify/src/components/VContent/VContent.sass' +//@import './vuetify/packages/vuetify/src/components/VCounter/VCounter.sass' +//@import './vuetify/packages/vuetify/src/components/VData/VData.sass' +//@import './vuetify/packages/vuetify/src/components/VDataIterator/VDataIterator.sass' +//@import './vuetify/packages/vuetify/src/components/VDataTable/VDataTable.sass' +//@import './vuetify/packages/vuetify/src/components/VDatePicker/VDatePicker.sass' +//@import './vuetify/packages/vuetify/src/components/VDialog/VDialog.sass' +//@import './vuetify/packages/vuetify/src/components/VDivider/VDivider.sass' +//@import './vuetify/packages/vuetify/src/components/VExpansionPanel/VExpansionPanel.sass' +//@import './vuetify/packages/vuetify/src/components/VFileInput/VFileInput.sass' +//@import './vuetify/packages/vuetify/src/components/VFooter/VFooter.sass' +//@import './vuetify/packages/vuetify/src/components/VForm/VForm.sass' +//@import './vuetify/packages/vuetify/src/components/VGrid/VGrid.sass' +//@import './vuetify/packages/vuetify/src/components/VHover/VHover.sass' +//@import './vuetify/packages/vuetify/src/components/VIcon/VIcon.sass' +//@import './vuetify/packages/vuetify/src/components/VImg/VImg.sass' +//@import './vuetify/packages/vuetify/src/components/VInput/VInput.sass' +//@import './vuetify/packages/vuetify/src/components/VItemGroup/VItemGroup.sass' +//@import './vuetify/packages/vuetify/src/components/VLabel/VLabel.sass' +//@import './vuetify/packages/vuetify/src/components/VList/VList.sass' +//@import './vuetify/packages/vuetify/src/components/VMenu/VMenu.sass' +//@import './vuetify/packages/vuetify/src/components/VMessages/VMessages.sass' +@import './vuetify/packages/vuetify/src/components/VNavigationDrawer/VNavigationDrawer.sass' +//@import './vuetify/packages/vuetify/src/components/VOverflowBtn/VOverflowBtn.sass' +//@import './vuetify/packages/vuetify/src/components/VOverlay/VOverlay.sass' +//@import './vuetify/packages/vuetify/src/components/VPagination/VPagination.sass' +//@import './vuetify/packages/vuetify/src/components/VParallax/VParallax.sass' +//@import './vuetify/packages/vuetify/src/components/VPicker/VPicker.sass' +//@import './vuetify/packages/vuetify/src/components/VProgressCircular/VProgressCircular.sass' +//@import './vuetify/packages/vuetify/src/components/VProgressLinear/VProgressLinear.sass' +//@import './vuetify/packages/vuetify/src/components/VRadioGroup/VRadioGroup.sass' +//@import './vuetify/packages/vuetify/src/components/VRangeSlider/VRangeSlider.sass' +//@import './vuetify/packages/vuetify/src/components/VRating/VRating.sass' +//@import './vuetify/packages/vuetify/src/components/VResponsive/VResponsive.sass' +//@import './vuetify/packages/vuetify/src/components/VSelect/VSelect.sass' +//@import './vuetify/packages/vuetify/src/components/VSheet/VSheet.sass' +//@import './vuetify/packages/vuetify/src/components/VSlideGroup/VSlideGroup.sass' +//@import './vuetify/packages/vuetify/src/components/VSlider/VSlider.sass' +//@import './vuetify/packages/vuetify/src/components/VSnackbar/VSnackbar.sass' +//@import './vuetify/packages/vuetify/src/components/VSparkline/VSparkline.sass' +//@import './vuetify/packages/vuetify/src/components/VSpeedDial/VSpeedDial.sass' +//@import './vuetify/packages/vuetify/src/components/VStepper/VStepper.sass' +//@import './vuetify/packages/vuetify/src/components/VSubheader/VSubheader.sass' +//@import './vuetify/packages/vuetify/src/components/VSwitch/VSwitch.sass' +//@import './vuetify/packages/vuetify/src/components/VSystemBar/VSystemBar.sass' +//@import './vuetify/packages/vuetify/src/components/VTabs/VTabs.sass' +//@import './vuetify/packages/vuetify/src/components/VTextarea/VTextarea.sass' +//@import './vuetify/packages/vuetify/src/components/VTextField/VTextField.sass' +//@import './vuetify/packages/vuetify/src/components/VTimeline/VTimeline.sass' +//@import './vuetify/packages/vuetify/src/components/VTimePicker/VTimePicker.sass' +@import './vuetify/packages/vuetify/src/components/VToolbar/VToolbar.sass' +//@import './vuetify/packages/vuetify/src/components/VTooltip/VTooltip.sass' +//@import './vuetify/packages/vuetify/src/components/VTreeview/VTreeview.sass' +//@import './vuetify/packages/vuetify/src/components/VWindow/VWindow.sass' diff --git a/ui/styles/vuetify b/ui/styles/vuetify new file mode 160000 index 0000000..ac4f3ce --- /dev/null +++ b/ui/styles/vuetify @@ -0,0 +1 @@ +Subproject commit ac4f3ceab6ac1dcc00ad4ba060b6d9ea36986357 From daecfc7a5bfb9ffceec946c9029085327cb00e99 Mon Sep 17 00:00:00 2001 From: Denis Kolodin Date: Sun, 18 Aug 2019 09:28:15 +0900 Subject: [PATCH 22/27] Use vuetify styles for navigation drawer --- ui/src/widgets/app.rs | 9 ++++++++- ui/src/widgets/list.rs | 19 +++++++++++++------ ui/src/widgets/navigation_drawer.rs | 11 ++++++++--- 3 files changed, 29 insertions(+), 10 deletions(-) diff --git a/ui/src/widgets/app.rs b/ui/src/widgets/app.rs index 2eddeb0..cd0a145 100644 --- a/ui/src/widgets/app.rs +++ b/ui/src/widgets/app.rs @@ -30,13 +30,20 @@ impl Widget for Model { } fn main_view(&self) -> View { + let mut v_application = vec!["v-application"]; + // TODO: Check `rtl` flag in app + v_application.push("v-application--is-ltr"); + // TODO: Check `dark` flag in app + v_application.push("theme--light"); + let mut app_bar_style = String::new(); app_bar_style.push_str("margin-top: 0px;"); app_bar_style.push_str("transform: translateY(0px);"); app_bar_style.push_str("left: 256px;"); app_bar_style.push_str("right: 0px;"); + html! { -
+
diff --git a/ui/src/widgets/list.rs b/ui/src/widgets/list.rs index 345204b..8b19fdb 100644 --- a/ui/src/widgets/list.rs +++ b/ui/src/widgets/list.rs @@ -29,12 +29,16 @@ impl Widget for Model { } fn main_view(&self) -> View { - let mut classes = vec!["list"]; + let mut v_list = vec!["v-list"]; + v_list.push("v-sheet"); + v_list.push("v-sheet--tile"); + // TODO: How to get theme parameter here? + v_list.push("theme--light"); if self.list.dense { - classes.push("dense"); + v_list.push("v-list--dense"); } html! { -
+
{ for self.list.items.iter().map(|item| self.view_item(item)) }
} @@ -43,12 +47,15 @@ impl Widget for Model { impl Model { fn view_item(&self, item: &protocol::ListItem) -> View { + let mut v_list_item = vec!["v-list-item"]; + v_list_item.push("v-list-item--link"); + v_list_item.push("theme--light"); html! { -
-
+
+
{ widgets::Icon::new(item.action.clone()).render() }
-
+
{ &item.content.caption }
diff --git a/ui/src/widgets/navigation_drawer.rs b/ui/src/widgets/navigation_drawer.rs index fa5a8ed..8765cfb 100644 --- a/ui/src/widgets/navigation_drawer.rs +++ b/ui/src/widgets/navigation_drawer.rs @@ -29,16 +29,21 @@ impl Widget for Model { } fn main_view(&self) -> View { - let mut classes = vec!["v-navigation-drawer"]; - classes.push("v-navigation-drawer--fixed"); + let mut v_navigation_drawer = vec!["v-navigation-drawer"]; + v_navigation_drawer.push("v-navigation-drawer--fixed"); + v_navigation_drawer.push("v-navigation-drawer--open"); + // TODO: Maybe get it as a parameter from App parent? + v_navigation_drawer.push("theme--light"); + let mut drawer_style = String::new(); drawer_style.push_str("height: 100vh;"); drawer_style.push_str("top: 0px;"); drawer_style.push_str("max-height: calc(100% - 36px);"); drawer_style.push_str("transform: translateX(0%);"); drawer_style.push_str("width: 256px;"); + html! { -
+
From eb5c6f7f05138864060664ca0abfb853e2a760e6 Mon Sep 17 00:00:00 2001 From: Denis Kolodin Date: Sun, 18 Aug 2019 10:47:28 +0900 Subject: [PATCH 23/27] Add Material Icon font --- examples/baseline/main.rs | 3 ++- protocol/src/lib.rs | 1 + ui/src/widgets/icon.rs | 15 ++++++++++++++- ui/styles/styles.sass | 10 +++++++--- 4 files changed, 24 insertions(+), 5 deletions(-) diff --git a/examples/baseline/main.rs b/examples/baseline/main.rs index 34c372b..3eee630 100644 --- a/examples/baseline/main.rs +++ b/examples/baseline/main.rs @@ -20,7 +20,8 @@ pub async fn main() -> Result<(), Error> { Scene(App( NavigationDrawer( List(vec![ - ListItem(Icon::Home, "MenuItem".into()), + ListItem(Icon::Home, "Home".into()), + ListItem(Icon::ContactMail, "Contact".into()), ]) ), Container( diff --git a/protocol/src/lib.rs b/protocol/src/lib.rs index f84e21a..972bdcc 100644 --- a/protocol/src/lib.rs +++ b/protocol/src/lib.rs @@ -82,6 +82,7 @@ pub struct ListItem { #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] pub enum Icon { Home, + ContactMail, MenuSandwich, } diff --git a/ui/src/widgets/icon.rs b/ui/src/widgets/icon.rs index dd41986..99f41c1 100644 --- a/ui/src/widgets/icon.rs +++ b/ui/src/widgets/icon.rs @@ -11,8 +11,21 @@ impl Icon { } pub fn render(&self) -> Html { + let mut v_icon = vec!["v-icon"]; + v_icon.push("notranslate"); + v_icon.push("material-icons"); + v_icon.push("theme--light"); html! { -

{ "Icon"}

+ { self.to_class() } + } + } + + fn to_class(&self) -> &'static str { + use protocol::Icon::*; + match self.icon { + Home => "home", + ContactMail => "contact_mail", + MenuSandwich => "_change it in Rust source", } } } diff --git a/ui/styles/styles.sass b/ui/styles/styles.sass index e07c0b8..1c55586 100644 --- a/ui/styles/styles.sass +++ b/ui/styles/styles.sass @@ -1,3 +1,4 @@ +@import url('https://fonts.googleapis.com/icon?family=Material+Icons') @import './vuetify/packages/vuetify/src/styles/main.sass' //@import './vuetify/packages/vuetify/src/components/VAlert/VAlert.sass' @import './vuetify/packages/vuetify/src/components/VApp/VApp.sass' @@ -33,12 +34,15 @@ //@import './vuetify/packages/vuetify/src/components/VForm/VForm.sass' //@import './vuetify/packages/vuetify/src/components/VGrid/VGrid.sass' //@import './vuetify/packages/vuetify/src/components/VHover/VHover.sass' -//@import './vuetify/packages/vuetify/src/components/VIcon/VIcon.sass' +@import './vuetify/packages/vuetify/src/components/VIcon/VIcon.sass' //@import './vuetify/packages/vuetify/src/components/VImg/VImg.sass' //@import './vuetify/packages/vuetify/src/components/VInput/VInput.sass' //@import './vuetify/packages/vuetify/src/components/VItemGroup/VItemGroup.sass' //@import './vuetify/packages/vuetify/src/components/VLabel/VLabel.sass' -//@import './vuetify/packages/vuetify/src/components/VList/VList.sass' +@import './vuetify/packages/vuetify/src/components/VList/VList.sass' +@import './vuetify/packages/vuetify/src/components/VList/VListGroup.sass' +@import './vuetify/packages/vuetify/src/components/VList/VListItem.sass' +@import './vuetify/packages/vuetify/src/components/VList/VListItemGroup.sass' //@import './vuetify/packages/vuetify/src/components/VMenu/VMenu.sass' //@import './vuetify/packages/vuetify/src/components/VMessages/VMessages.sass' @import './vuetify/packages/vuetify/src/components/VNavigationDrawer/VNavigationDrawer.sass' @@ -54,7 +58,7 @@ //@import './vuetify/packages/vuetify/src/components/VRating/VRating.sass' //@import './vuetify/packages/vuetify/src/components/VResponsive/VResponsive.sass' //@import './vuetify/packages/vuetify/src/components/VSelect/VSelect.sass' -//@import './vuetify/packages/vuetify/src/components/VSheet/VSheet.sass' +@import './vuetify/packages/vuetify/src/components/VSheet/VSheet.sass' //@import './vuetify/packages/vuetify/src/components/VSlideGroup/VSlideGroup.sass' //@import './vuetify/packages/vuetify/src/components/VSlider/VSlider.sass' //@import './vuetify/packages/vuetify/src/components/VSnackbar/VSnackbar.sass' From c4dec49da77c4b7a82e0edd3fbabeda3d736c7b2 Mon Sep 17 00:00:00 2001 From: Denis Kolodin Date: Sun, 18 Aug 2019 20:09:56 +0900 Subject: [PATCH 24/27] Move AppBar to a separate module --- ui/src/widgets/app.rs | 13 +-------- ui/src/widgets/app_bar.rs | 57 +++++++++++++++++++++++++++++++++++++++ ui/src/widgets/list.rs | 4 ++- ui/src/widgets/mod.rs | 3 +++ ui/styles/styles.sass | 3 ++- 5 files changed, 66 insertions(+), 14 deletions(-) create mode 100644 ui/src/widgets/app_bar.rs diff --git a/ui/src/widgets/app.rs b/ui/src/widgets/app.rs index cd0a145..abe047d 100644 --- a/ui/src/widgets/app.rs +++ b/ui/src/widgets/app.rs @@ -36,22 +36,11 @@ impl Widget for Model { // TODO: Check `dark` flag in app v_application.push("theme--light"); - let mut app_bar_style = String::new(); - app_bar_style.push_str("margin-top: 0px;"); - app_bar_style.push_str("transform: translateY(0px);"); - app_bar_style.push_str("left: 256px;"); - app_bar_style.push_str("right: 0px;"); - html! {
-
-
-
-
{ &self.app.app_bar.title.caption }
-
-
+
diff --git a/ui/src/widgets/app_bar.rs b/ui/src/widgets/app_bar.rs new file mode 100644 index 0000000..49a286b --- /dev/null +++ b/ui/src/widgets/app_bar.rs @@ -0,0 +1,57 @@ +use crate::widgets::{self, Reqs, View, Widget, WidgetModel}; +use yew::{html, Properties}; + +pub type AppBarWidget = WidgetModel; + +pub struct Model { + app_bar: protocol::Bar, +} + +#[derive(Properties, PartialEq, Clone)] +pub struct Props { + #[props(required)] + pub app_bar: protocol::Bar, +} + +impl Widget for Model { + type Message = (); + type Properties = Props; + + fn produce(props: &Self::Properties) -> Self { + Self { + app_bar: props.app_bar.clone(), + } + } + + fn recompose(&mut self, props: &Self::Properties) -> Reqs { + self.app_bar = props.app_bar.to_owned(); + None + } + + fn main_view(&self) -> View { + let mut v_app_bar = vec!["v-app-bar"]; + v_app_bar.push("v-app-bar--fixed"); + v_app_bar.push("v-sheet"); + v_app_bar.push("v-sheet--tile"); + // TODO: Changeable + v_app_bar.push("theme--dark"); + v_app_bar.push("v-toolbar"); + // TODO: Changeable + v_app_bar.push("indigo"); + + let mut app_bar_style = String::new(); + app_bar_style.push_str("margin-top: 0px;"); + app_bar_style.push_str("transform: translateY(0px);"); + app_bar_style.push_str("left: 256px;"); + app_bar_style.push_str("right: 0px;"); + + html! { +
+
+
+
{ &self.app_bar.title.caption }
+
+
+ } + } +} diff --git a/ui/src/widgets/list.rs b/ui/src/widgets/list.rs index 8b19fdb..2a80e7b 100644 --- a/ui/src/widgets/list.rs +++ b/ui/src/widgets/list.rs @@ -56,7 +56,9 @@ impl Model { { widgets::Icon::new(item.action.clone()).render() }
- { &item.content.caption } +
+ { &item.content.caption } +
} diff --git a/ui/src/widgets/mod.rs b/ui/src/widgets/mod.rs index 386bf50..6386fe0 100644 --- a/ui/src/widgets/mod.rs +++ b/ui/src/widgets/mod.rs @@ -35,6 +35,9 @@ pub use welcome::WelcomeWidget as Welcome; mod app; pub use app::AppWidget as App; +mod app_bar; +pub use app_bar::AppBarWidget as AppBar; + mod container; pub use container::ContainerWidget as Container; diff --git a/ui/styles/styles.sass b/ui/styles/styles.sass index 1c55586..eb35fd3 100644 --- a/ui/styles/styles.sass +++ b/ui/styles/styles.sass @@ -1,4 +1,5 @@ -@import url('https://fonts.googleapis.com/icon?family=Material+Icons') +@import url('https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900%7CRoboto+Mono:500%7CMaterial+Icons') + @import './vuetify/packages/vuetify/src/styles/main.sass' //@import './vuetify/packages/vuetify/src/components/VAlert/VAlert.sass' @import './vuetify/packages/vuetify/src/components/VApp/VApp.sass' From 8619680425780ae51c64814e441c57e8b7768600 Mon Sep 17 00:00:00 2001 From: Denis Kolodin Date: Sun, 18 Aug 2019 20:25:59 +0900 Subject: [PATCH 25/27] Add footer block to App --- ui/src/widgets/app.rs | 20 +++++++++++++++++--- ui/src/widgets/container.rs | 7 ++++--- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/ui/src/widgets/app.rs b/ui/src/widgets/app.rs index abe047d..df41998 100644 --- a/ui/src/widgets/app.rs +++ b/ui/src/widgets/app.rs @@ -36,15 +36,29 @@ impl Widget for Model { // TODO: Check `dark` flag in app v_application.push("theme--light"); + let v_content_style = "padding: 64px 0px 36px 256px;"; + + let mut v_footer = vec!["v-footer"]; + v_footer.push("v-footer--fixed"); + v_footer.push("v-sheet"); + v_footer.push("v-sheet--tile"); + v_footer.push("theme--light"); + v_footer.push("indigo"); + + let v_footer_style = "left: 0px; right: 0px; bottom: 0px;"; + html! {
-
- +
+
+ +
-
diff --git a/ui/src/widgets/container.rs b/ui/src/widgets/container.rs index 1b90f7a..cb4cf96 100644 --- a/ui/src/widgets/container.rs +++ b/ui/src/widgets/container.rs @@ -30,12 +30,13 @@ impl Widget for Model { } fn main_view(&self) -> View { - let mut classes = vec!["container"]; + let mut v_container = vec!["container"]; + v_container.push("fill-height"); if self.container.fluid { - classes.push("fluid"); + v_container.push("container--fluid"); } html! { -
+
} From 4a2912f9802aa0538dd66352bba8859c5b446a2e Mon Sep 17 00:00:00 2001 From: Denis Kolodin Date: Sun, 18 Aug 2019 20:32:10 +0900 Subject: [PATCH 26/27] Move Footer to a separate widget module --- protocol/src/lib.rs | 5 +++++ src/dsl.rs | 1 + ui/src/widgets/app.rs | 13 +----------- ui/src/widgets/footer.rs | 46 ++++++++++++++++++++++++++++++++++++++++ ui/src/widgets/mod.rs | 3 +++ 5 files changed, 56 insertions(+), 12 deletions(-) create mode 100644 ui/src/widgets/footer.rs diff --git a/protocol/src/lib.rs b/protocol/src/lib.rs index 972bdcc..a47038c 100644 --- a/protocol/src/lib.rs +++ b/protocol/src/lib.rs @@ -60,6 +60,7 @@ pub struct App { pub navigation_drawer: NavigationDrawer, pub app_bar: Bar, pub content: Container, + pub footer: Footer, } #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] @@ -97,6 +98,10 @@ pub struct Bar { pub title: Title, } +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] +pub struct Footer { +} + #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] pub struct Container { pub fluid: bool, diff --git a/src/dsl.rs b/src/dsl.rs index 8022557..909d766 100644 --- a/src/dsl.rs +++ b/src/dsl.rs @@ -17,6 +17,7 @@ pub fn App(navigation_drawer: protocol::NavigationDrawer, content: protocol::Con } }, content, + footer: protocol::Footer { }, } } diff --git a/ui/src/widgets/app.rs b/ui/src/widgets/app.rs index df41998..3803cf2 100644 --- a/ui/src/widgets/app.rs +++ b/ui/src/widgets/app.rs @@ -38,15 +38,6 @@ impl Widget for Model { let v_content_style = "padding: 64px 0px 36px 256px;"; - let mut v_footer = vec!["v-footer"]; - v_footer.push("v-footer--fixed"); - v_footer.push("v-sheet"); - v_footer.push("v-sheet--tile"); - v_footer.push("theme--light"); - v_footer.push("indigo"); - - let v_footer_style = "left: 0px; right: 0px; bottom: 0px;"; - html! {
@@ -57,9 +48,7 @@ impl Widget for Model {
- +
} diff --git a/ui/src/widgets/footer.rs b/ui/src/widgets/footer.rs new file mode 100644 index 0000000..cd72096 --- /dev/null +++ b/ui/src/widgets/footer.rs @@ -0,0 +1,46 @@ +use crate::widgets::{self, Reqs, View, Widget, WidgetModel}; +use yew::{html, Properties}; + +pub type FooterWidget = WidgetModel; + +pub struct Model { + footer: protocol::Footer, +} + +#[derive(Properties, PartialEq, Clone)] +pub struct Props { + #[props(required)] + pub footer: protocol::Footer, +} + +impl Widget for Model { + type Message = (); + type Properties = Props; + + fn produce(props: &Self::Properties) -> Self { + Self { + footer: props.footer.clone(), + } + } + + fn recompose(&mut self, props: &Self::Properties) -> Reqs { + self.footer = props.footer.to_owned(); + None + } + + fn main_view(&self) -> View { + let mut v_footer = vec!["v-footer"]; + v_footer.push("v-footer--fixed"); + v_footer.push("v-sheet"); + v_footer.push("v-sheet--tile"); + v_footer.push("theme--light"); + v_footer.push("indigo"); + let v_footer_style = "left: 0px; right: 0px; bottom: 0px;"; + html! { + + } + } +} + diff --git a/ui/src/widgets/mod.rs b/ui/src/widgets/mod.rs index 6386fe0..9407368 100644 --- a/ui/src/widgets/mod.rs +++ b/ui/src/widgets/mod.rs @@ -41,6 +41,9 @@ pub use app_bar::AppBarWidget as AppBar; mod container; pub use container::ContainerWidget as Container; +mod footer; +pub use footer::FooterWidget as Footer; + mod icon; pub use icon::Icon; From 6c37203098d88cbc9c30a1102917319754016349 Mon Sep 17 00:00:00 2001 From: Denis Kolodin Date: Sun, 18 Aug 2019 22:13:29 +0900 Subject: [PATCH 27/27] Activate styles for Footer --- src/dsl.rs | 2 +- ui/styles/styles.sass | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/dsl.rs b/src/dsl.rs index 909d766..d5743db 100644 --- a/src/dsl.rs +++ b/src/dsl.rs @@ -46,7 +46,7 @@ pub fn ListItem(icon: protocol::Icon, title: String) -> protocol::ListItem { pub fn Container(layout: protocol::Layout) -> protocol::Container { protocol::Container { layout, - fluid: false, + fluid: true, } } diff --git a/ui/styles/styles.sass b/ui/styles/styles.sass index eb35fd3..8a77a53 100644 --- a/ui/styles/styles.sass +++ b/ui/styles/styles.sass @@ -21,7 +21,7 @@ //@import './vuetify/packages/vuetify/src/components/VChipGroup/VChipGroup.sass' //@import './vuetify/packages/vuetify/src/components/VColorPicker/VColorPicker.sass' //@import './vuetify/packages/vuetify/src/components/VCombobox/VCombobox.sass' -//@import './vuetify/packages/vuetify/src/components/VContent/VContent.sass' +@import './vuetify/packages/vuetify/src/components/VContent/VContent.sass' //@import './vuetify/packages/vuetify/src/components/VCounter/VCounter.sass' //@import './vuetify/packages/vuetify/src/components/VData/VData.sass' //@import './vuetify/packages/vuetify/src/components/VDataIterator/VDataIterator.sass' @@ -31,9 +31,9 @@ //@import './vuetify/packages/vuetify/src/components/VDivider/VDivider.sass' //@import './vuetify/packages/vuetify/src/components/VExpansionPanel/VExpansionPanel.sass' //@import './vuetify/packages/vuetify/src/components/VFileInput/VFileInput.sass' -//@import './vuetify/packages/vuetify/src/components/VFooter/VFooter.sass' +@import './vuetify/packages/vuetify/src/components/VFooter/VFooter.sass' //@import './vuetify/packages/vuetify/src/components/VForm/VForm.sass' -//@import './vuetify/packages/vuetify/src/components/VGrid/VGrid.sass' +@import './vuetify/packages/vuetify/src/components/VGrid/VGrid.sass' //@import './vuetify/packages/vuetify/src/components/VHover/VHover.sass' @import './vuetify/packages/vuetify/src/components/VIcon/VIcon.sass' //@import './vuetify/packages/vuetify/src/components/VImg/VImg.sass'