summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjelemux <jeremias.weber@protonmail.com>2021-02-09 23:18:45 +0100
committerjelemux <jeremias.weber@protonmail.com>2021-02-09 23:18:45 +0100
commit036a567bae8346eb38f9237f59645dbcc4f1cd8c (patch)
tree21a86e3c5cb8964030c414718190af12f3d26125
parent9df3ff8d633a18e934d4e62b0e2e718620760552 (diff)
downloadwasm-card-036a567bae8346eb38f9237f59645dbcc4f1cd8c.tar.gz
wasm-card-036a567bae8346eb38f9237f59645dbcc4f1cd8c.tar.bz2
switch to cargo-make; format files with rustfmt
-rw-r--r--Makefile.toml71
-rw-r--r--Readme.md25
-rw-r--r--index.html (renamed from static/index.html)8
-rw-r--r--src/lib.rs10
-rw-r--r--src/view/address.rs28
-rw-r--r--src/view/dates.rs18
-rw-r--r--src/view/main.rs345
-rw-r--r--src/view/mod.rs25
-rw-r--r--src/view/name.rs28
-rw-r--r--src/view/organizational.rs20
-rw-r--r--src/view/telephone.rs26
-rw-r--r--src/viewmodel/address.rs36
-rw-r--r--src/viewmodel/dates.rs16
-rw-r--r--src/viewmodel/mod.rs103
-rw-r--r--src/viewmodel/name.rs31
-rw-r--r--src/viewmodel/organizational.rs71
-rw-r--r--src/viewmodel/telephone.rs27
-rw-r--r--src/viewmodel/utility.rs6
-rw-r--r--src/viewmodel/vcard.rs8
19 files changed, 483 insertions, 419 deletions
diff --git a/Makefile.toml b/Makefile.toml
new file mode 100644
index 0000000..00ea9b9
--- /dev/null
+++ b/Makefile.toml
@@ -0,0 +1,71 @@
+[env]
+PORT = "8000"
+
+[config]
+skip_core_tasks = true
+
+# ---- BASIC ----
+
+[tasks.watch]
+description = "Watch files and recompile the project on change"
+run_task = [
+ { name = "build" },
+]
+watch = true
+
+[tasks.serve]
+description = "Start server"
+install_crate = { crate_name = "microserver", binary = "microserver", test_arg = "-h" }
+command = "microserver"
+args = ["--port", "${PORT}"]
+
+[tasks.verify]
+description = "Format, lint with Clippy and run tests"
+dependencies = ["fmt", "clippy", "test_h_firefox"]
+
+# ---- BUILD ----
+
+[tasks.build]
+description = "Build with wasm-pack"
+install_crate = { crate_name = "wasm-pack", binary = "wasm-pack", test_arg = "-V" }
+command = "wasm-pack"
+args = ["build", "--target", "web", "--out-name", "app", "--dev", "--debug"]
+
+[tasks.build_release]
+description = "Build with wasm-pack in release mode"
+install_crate = { crate_name = "wasm-pack", binary = "wasm-pack", test_arg = "-V" }
+command = "wasm-pack"
+args = ["build", "--target", "web", "--out-name", "app", "--release"]
+
+# ---- LINT ----
+
+[tasks.clippy]
+description = "Lint with Clippy"
+install_crate = { rustup_component_name = "clippy", binary = "cargo-clippy", test_arg = "--help" }
+command = "cargo"
+args = ["clippy", "--all-features", "--", "--deny", "warnings", "--deny", "clippy::pedantic", "--deny", "clippy::nursery"]
+
+[tasks.fmt]
+description = "Format with rustfmt"
+install_crate = { rustup_component_name = "rustfmt", binary = "rustfmt", test_arg = "-V" }
+command = "cargo"
+args = ["fmt"]
+
+
+# ---- TEST ----
+
+[tasks.test_h]
+description = "Run headless tests. Ex: 'cargo make test_h firefox'. Test envs: [chrome, firefox, safari]"
+extend = "test"
+args = ["test", "--headless", "--${@}"]
+
+[tasks.test_h_firefox]
+description = "Run headless tests with Firefox."
+extend = "test"
+args = ["test", "--headless", "--firefox"]
+
+[tasks.test]
+description = "Run tests. Ex: 'cargo make test firefox'. Test envs: [chrome, firefox, safari]"
+install_crate = { crate_name = "wasm-pack", binary = "wasm-pack", test_arg = "-V" }
+command = "wasm-pack"
+args = ["test", "--${@}"] \ No newline at end of file
diff --git a/Readme.md b/Readme.md
index cb0e50a..b257c04 100644
--- a/Readme.md
+++ b/Readme.md
@@ -32,23 +32,32 @@ Supports generating vCards (.vcf), print-ready PDF business cards and QR Codes.
* [Standard rust toolchain](https://www.rust-lang.org/tools/install)
* [wasm-pack](https://rustwasm.github.io/wasm-pack/installer/)
-* HTTP Server (python has one!)
+* cargo-make: `cargo install cargo-make`
-### 📦 Build with `wasm-pack build`
-
+### 📦 Build
+Debug:
+```
+cargo make build
+```
+Release:
```
-wasm-pack build --target web
+cargo make build_release
```
-### 🔍 Use the debug flag for tracing errors
+### 🍲 Serve
```
-wasm-pack build --debug --target web
+cargo make serve
```
-### 🎬 Run on python server
+### 🔍 Linting
+
+```
+cargo make clippy
+```
+### 📏 Format
```
-python -m http.server 8000
+cargo make fmt
``` \ No newline at end of file
diff --git a/static/index.html b/index.html
index c067b51..7c91ad5 100644
--- a/static/index.html
+++ b/index.html
@@ -3,16 +3,16 @@
<head>
<meta charset="utf-8">
- <link rel="icon" href="./favicon.ico" type="image/png" />
- <link rel="stylesheet" href="./bulma.min.css" />
- <link rel="stylesheet" href="./fontawesome-solid.min.css" />
+ <link rel="icon" href="./static/favicon.ico" type="image/png" />
+ <link rel="stylesheet" href="./static/bulma.min.css" />
+ <link rel="stylesheet" href="./static/fontawesome-solid.min.css" />
<title>BCard Wasm Web App</title>
</head>
<body>
<script type="module">
Error.stackTraceLimit = Infinity;
- import init from "../pkg/bcard_wasm_webapp.js";
+ import init from "./pkg/app.js";
init();
</script>
<noscript>This page contains webassembly and javascript content, please enable javascript in your
diff --git a/src/lib.rs b/src/lib.rs
index 401e996..b8e10a5 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,10 +1,10 @@
-#![recursion_limit="1024"]
-extern crate wee_alloc;
+#![recursion_limit = "1024"]
extern crate console_error_panic_hook;
-use wasm_bindgen::prelude::*;
-use yew::prelude::App;
+extern crate wee_alloc;
use std::panic;
use view::main::MainView;
+use wasm_bindgen::prelude::*;
+use yew::prelude::App;
// Use `wee_alloc` as the global allocator.
#[global_allocator]
@@ -21,4 +21,4 @@ fn init() {
pub fn run_app() {
init();
App::<MainView>::new().mount_to_body();
-} \ No newline at end of file
+}
diff --git a/src/view/address.rs b/src/view/address.rs
index a945272..57ea7e4 100644
--- a/src/view/address.rs
+++ b/src/view/address.rs
@@ -1,28 +1,28 @@
+use super::VCardPropertyInputComponent;
use crate::view::InputProps;
-use yew::prelude::*;
-use yewtil::NeqAssign;
use crate::viewmodel::address::*;
-use crate::viewmodel::VCardPropertyInputObject;
-use super::VCardPropertyInputComponent;
use crate::viewmodel::Error;
+use crate::viewmodel::VCardPropertyInputObject;
+use yew::prelude::*;
+use yewtil::NeqAssign;
-type Props = InputProps<Address,AddressView>;
+type Props = InputProps<Address, AddressView>;
/// View Component for a `address` field
-///
+///
/// # Examples
-///
+///
/// ```compile_fail
/// let html = html!{
-/// <AddressView weak_link=some_weak_component_link
+/// <AddressView weak_link=some_weak_component_link
/// generated=self.link.callback(
-/// |n: Irc<Address>|
+/// |n: Irc<Address>|
/// Msg::GeneratedAddress(some_address)
/// )
/// />
/// };
/// ```
-#[derive(Clone,PartialEq)]
+#[derive(Clone, PartialEq)]
pub struct AddressView {
props: Props,
value: Address,
@@ -79,17 +79,17 @@ impl Component for AddressView {
Msg::ToggleHome => self.value.home = !self.value.home,
Msg::Generate => {
self.props.generated.emit(self.value.clone());
- },
+ }
};
true
}
- fn change(&mut self, props: <Self as yew::Component>::Properties) -> bool {
+ fn change(&mut self, props: <Self as yew::Component>::Properties) -> bool {
self.props.neq_assign(props)
}
fn view(&self) -> yew::virtual_dom::VNode {
let link = self.props.weak_link.borrow().clone().unwrap();
- html!{
+ html! {
<div class="box">
{ self.render_error() }
@@ -100,4 +100,4 @@ impl Component for AddressView {
</div>
}
}
-} \ No newline at end of file
+}
diff --git a/src/view/dates.rs b/src/view/dates.rs
index de3d311..b2a6dd3 100644
--- a/src/view/dates.rs
+++ b/src/view/dates.rs
@@ -1,14 +1,14 @@
+use super::VCardPropertyInputComponent;
use crate::view::InputProps;
-use yew::prelude::*;
-use yewtil::NeqAssign;
-use crate::viewmodel::Error;
use crate::viewmodel::dates::*;
+use crate::viewmodel::Error;
use crate::viewmodel::VCardPropertyInputObject;
-use super::VCardPropertyInputComponent;
+use yew::prelude::*;
+use yewtil::NeqAssign;
-type Props = InputProps<Dates,DatesView>;
+type Props = InputProps<Dates, DatesView>;
-#[derive(Clone,PartialEq)]
+#[derive(Clone, PartialEq)]
pub struct DatesView {
props: Props,
value: Dates,
@@ -51,7 +51,7 @@ impl Component for DatesView {
Msg::UpdateBirthday(b) => self.value.birthday = b,
Msg::Generate => {
self.props.generated.emit(self.value.clone());
- },
+ }
};
true
}
@@ -61,7 +61,7 @@ impl Component for DatesView {
fn view(&self) -> yew::virtual_dom::VNode {
let link = self.props.weak_link.borrow().clone().unwrap();
- html!{
+ html! {
<div class="box">
{ self.render_error() }
@@ -72,4 +72,4 @@ impl Component for DatesView {
</div>
}
}
-} \ No newline at end of file
+}
diff --git a/src/view/main.rs b/src/view/main.rs
index d6b2cb9..196afa0 100644
--- a/src/view/main.rs
+++ b/src/view/main.rs
@@ -1,30 +1,29 @@
-use crate::viewmodel::organizational::Organizational;
-use crate::view::organizational::{self,OrganizationalView};
+use super::address::{self, AddressView};
+use super::dates::{self, DatesView};
+use super::name::{self, NameView};
+use super::WeakComponentLink;
+use crate::view::organizational::{self, OrganizationalView};
+use crate::view::telephone::{self, TelephoneView};
+use crate::viewmodel::address::Address;
use crate::viewmodel::dates::Dates;
-use yew::services::ConsoleService;
+use crate::viewmodel::name::Name;
+use crate::viewmodel::organizational::Organizational;
+use crate::viewmodel::telephone::Telephone;
+use crate::viewmodel::utility::*;
use crate::viewmodel::vcard::VCardData;
use crate::viewmodel::Error;
-use crate::view::telephone::{self,TelephoneView};
use crate::viewmodel::VCardPropertyInputObject;
-use super::WeakComponentLink;
-use super::name::{self,NameView};
-use super::address::{self,AddressView};
-use super::dates::{self,DatesView};
+use boolinator::Boolinator;
+use chrono::prelude::*;
use genpdf::Element as _;
-use genpdf::{elements, style, fonts};
+use genpdf::{elements, fonts, style};
use qrcodegen::QrCode;
use qrcodegen::QrCodeEcc;
+use vobject::parameters;
+use vobject::vcard::VcardBuilder;
use yew::prelude::*;
+use yew::services::ConsoleService;
use yewtil::ptr::Mrc;
-use vobject::vcard::VcardBuilder;
-use vobject::parameters;
-use chrono::prelude::*;
-use crate::viewmodel::name::Name;
-use crate::viewmodel::address::Address;
-use crate::viewmodel::telephone::Telephone;
-use crate::viewmodel::utility::*;
-use boolinator::Boolinator;
-
pub struct MainView {
link: ComponentLink<Self>,
@@ -67,10 +66,10 @@ impl Component for MainView {
type Properties = ();
fn create(_props: Self::Properties, link: ComponentLink<Self>) -> Self {
- MainView {
- link,
- error: None,
- download: None,
+ MainView {
+ link,
+ error: None,
+ download: None,
selected_option: DownloadOption::VCard,
vcard_data: Mrc::new(VCardData::new()),
@@ -91,31 +90,31 @@ impl Component for MainView {
Msg::AddName => {
self.name_links.push(WeakComponentLink::default());
shouldrender = true;
- },
+ }
Msg::AddAddress => {
self.address_links.push(WeakComponentLink::default());
shouldrender = true;
- },
+ }
Msg::AddTelephone => {
self.telephone_links.push(WeakComponentLink::default());
shouldrender = true;
- },
+ }
Msg::AddDates => {
self.dates_links.push(WeakComponentLink::default());
shouldrender = true;
- },
+ }
Msg::AddOrganizational => {
self.organizational_links.push(WeakComponentLink::default());
shouldrender = true;
- },
+ }
Msg::ChangeDownloadOption(option) => {
self.selected_option = option;
shouldrender = false;
- },
+ }
Msg::Generate => {
-
- if self.selected_option == DownloadOption::VCard || self.selected_option == DownloadOption::QrCode {
-
+ if self.selected_option == DownloadOption::VCard
+ || self.selected_option == DownloadOption::QrCode
+ {
for name_link in self.name_links.iter() {
let name_link = name_link.borrow().clone().unwrap();
name_link.send_message(name::Msg::Generate);
@@ -158,52 +157,55 @@ impl Component for MainView {
*/
shouldrender = true;
- },
+ }
Msg::GeneratedName(name) => {
-
self.answer_count += 1;
match self.vcard_data.get_mut() {
Some(vcard_data) => vcard_data.add_name(name),
- None => ConsoleService::info("Error in GeneratedName: Couldn't get mutable borrow of VCardData"),
+ None => ConsoleService::info(
+ "Error in GeneratedName: Couldn't get mutable borrow of VCardData",
+ ),
};
shouldrender = true;
-
- },
+ }
Msg::GeneratedAddress(address) => {
-
self.answer_count += 1;
match self.vcard_data.get_mut() {
Some(vcard_data) => vcard_data.add_address(address),
- None => ConsoleService::info("Error in GeneratedAddress: Couldn't get mutable borrow of VCardData"),
+ None => ConsoleService::info(
+ "Error in GeneratedAddress: Couldn't get mutable borrow of VCardData",
+ ),
};
-
+
shouldrender = true;
- },
+ }
Msg::GeneratedTelephone(telephone) => {
-
self.answer_count += 1;
match self.vcard_data.get_mut() {
Some(vcard_data) => vcard_data.add_telephone(telephone),
- None => ConsoleService::info("Error in GeneratedTelephone: Couldn't get mutable borrow of VCardData"),
+ None => ConsoleService::info(
+ "Error in GeneratedTelephone: Couldn't get mutable borrow of VCardData",
+ ),
};
shouldrender = true;
- },
+ }
Msg::GeneratedDates(dates) => {
-
self.answer_count += 1;
match self.vcard_data.get_mut() {
Some(vcard_data) => vcard_data.add_dates(dates),
- None => ConsoleService::info("Error in GeneratedDates: Couldn't get mutable borrow of VCardData"),
+ None => ConsoleService::info(
+ "Error in GeneratedDates: Couldn't get mutable borrow of VCardData",
+ ),
};
shouldrender = true;
- },
+ }
Msg::GeneratedOrganizational(organizational) => {
self.answer_count += 1;
@@ -213,9 +215,8 @@ impl Component for MainView {
};
shouldrender = true;
- },
+ }
Msg::GenerationComplete => {
-
self.answer_count = 0;
let vcard_data = self.vcard_data.clone_inner();
@@ -223,33 +224,20 @@ impl Component for MainView {
let mut builder = VcardBuilder::new();
for name in vcard_data.names {
-
if !name.is_empty() {
-
- builder = builder
- .with_fullname(
- name.generate_fn()
- )
- .with_name(
+ builder = builder.with_fullname(name.generate_fn()).with_name(
parameters!(),
- (!name.last_name.is_empty())
- .as_some(name.last_name.clone()),
- (!name.first_name.is_empty())
- .as_some(name.first_name.clone()),
- (!name.middle_name.is_empty())
- .as_some(name.middle_name.clone()),
- (!name.prefix.is_empty())
- .as_some(name.prefix.clone()),
- (!name.suffix.is_empty())
- .as_some(name.suffix.clone())
+ (!name.last_name.is_empty()).as_some(name.last_name.clone()),
+ (!name.first_name.is_empty()).as_some(name.first_name.clone()),
+ (!name.middle_name.is_empty()).as_some(name.middle_name.clone()),
+ (!name.prefix.is_empty()).as_some(name.prefix.clone()),
+ (!name.suffix.is_empty()).as_some(name.suffix.clone()),
);
}
}
for address in vcard_data.addresses {
-
if !address.is_empty() {
-
let mut types = String::new();
if address.work {
types.push_str("WORK");
@@ -260,37 +248,29 @@ impl Component for MainView {
}
types.push_str("HOME")
}
-
+
let params = if types.is_empty() {
parameters!()
} else {
parameters!("TYPE" => types)
};
-
+
builder = builder.with_adr(
params,
(!address.post_office_box.is_empty())
.as_some(address.post_office_box.clone()),
- (!address.extension.is_empty())
- .as_some(address.extension.clone()),
- (!address.street.is_empty())
- .as_some(address.street.clone()),
- (!address.locality.is_empty())
- .as_some(address.locality.clone()),
- (!address.region.is_empty())
- .as_some(address.region.clone()),
- (!address.code.is_empty())
- .as_some(address.code.clone()),
- (!address.country.is_empty())
- .as_some(address.country.clone()),
+ (!address.extension.is_empty()).as_some(address.extension.clone()),
+ (!address.street.is_empty()).as_some(address.street.clone()),
+ (!address.locality.is_empty()).as_some(address.locality.clone()),
+ (!address.region.is_empty()).as_some(address.region.clone()),
+ (!address.code.is_empty()).as_some(address.code.clone()),
+ (!address.country.is_empty()).as_some(address.country.clone()),
);
}
}
for telephone in vcard_data.telephones {
-
if !telephone.is_empty() {
-
let mut types = String::new();
if telephone.work {
types.push_str("WORK");
@@ -343,36 +323,28 @@ impl Component for MainView {
}
types.push_str("TEXTPHONE")
}
-
+
let params = if types.is_empty() {
parameters!()
} else {
parameters!("TYPE" => types)
};
-
- builder = builder.with_tel(
- params,
- telephone.number.clone(),
- );
+
+ builder = builder.with_tel(params, telephone.number.clone());
}
}
for dates in vcard_data.datess {
-
if !dates.anniversary.is_empty() {
builder = builder.with_anniversary(dates.anniversary);
}
if !dates.birthday.is_empty() {
- builder = builder.with_bday(
- parameters!(),
- dates.birthday
- );
+ builder = builder.with_bday(parameters!(), dates.birthday);
}
}
for organizational in vcard_data.organizationals {
-
if !organizational.org.is_empty() {
builder = builder.with_org(vec![organizational.org]);
}
@@ -398,50 +370,51 @@ impl Component for MainView {
builder = builder.with_related(organizational.related);
}
}
-
let rev = Local::now();
-
+
match builder
.with_version("4.0".to_string())
.with_rev(format!("{}", rev))
- .build() {
- Ok(vcard) => {
- match self.selected_option {
- DownloadOption::VCard => {
- self.download = Some(
- Download {
- file_name: String::from("VCard.vcs"),
- content: vobject::write_component(&vcard),
- mime_type: MimeType::VCard,
- }
- );
- },
- DownloadOption::QrCode => {
- match QrCode::encode_text(&vobject::write_component(&vcard), QrCodeEcc::Low) {
- Ok(qr) => self.download = Some(
- Download {
- file_name: String::from("QR-Code VCard.svg"),
- content: qr.to_svg_string(4),
- mime_type: MimeType::SVG,
- }
- ),
- Err(_) => self.error = Some(
- Error{
- msg: String::from("Sorry, VCard is too long!"),
- }
- ),
- };
- },
- _ => (),
- };
- },
- Err(err) => self.error = Some(
- Error{
- msg: err.to_string(),
+ .build()
+ {
+ Ok(vcard) => {
+ match self.selected_option {
+ DownloadOption::VCard => {
+ self.download = Some(Download {
+ file_name: String::from("VCard.vcs"),
+ content: vobject::write_component(&vcard),
+ mime_type: MimeType::VCard,
+ });
}
- ),
- };
+ DownloadOption::QrCode => {
+ match QrCode::encode_text(
+ &vobject::write_component(&vcard),
+ QrCodeEcc::Low,
+ ) {
+ Ok(qr) => {
+ self.download = Some(Download {
+ file_name: String::from("QR-Code VCard.svg"),
+ content: qr.to_svg_string(4),
+ mime_type: MimeType::SVG,
+ })
+ }
+ Err(_) => {
+ self.error = Some(Error {
+ msg: String::from("Sorry, VCard is too long!"),
+ })
+ }
+ };
+ }
+ _ => (),
+ };
+ }
+ Err(err) => {
+ self.error = Some(Error {
+ msg: err.to_string(),
+ })
+ }
+ };
match self.vcard_data.get_mut() {
Some(vcard_data) => *vcard_data = VCardData::new(),
@@ -449,8 +422,7 @@ impl Component for MainView {
};
shouldrender = true;
-
- },
+ }
Msg::Nope => shouldrender = false,
};
@@ -460,7 +432,7 @@ impl Component for MainView {
if self.error.is_some() {
self.download = None;
}
-
+
shouldrender
}
@@ -469,20 +441,17 @@ impl Component for MainView {
}
fn view(&self) -> Html {
-
- let download_options = self.link.callback(|e: ChangeData|
- match e {
- ChangeData::Select(v) => match v.value().as_str() {
- "vcard" => Msg::ChangeDownloadOption(DownloadOption::VCard),
- "pdf" => Msg::ChangeDownloadOption(DownloadOption::PDF),
- "qrcode" => Msg::ChangeDownloadOption(DownloadOption::QrCode),
- _ => Msg::Nope,
- },
+ let download_options = self.link.callback(|e: ChangeData| match e {
+ ChangeData::Select(v) => match v.value().as_str() {
+ "vcard" => Msg::ChangeDownloadOption(DownloadOption::VCard),
+ "pdf" => Msg::ChangeDownloadOption(DownloadOption::PDF),
+ "qrcode" => Msg::ChangeDownloadOption(DownloadOption::QrCode),
_ => Msg::Nope,
- }
- );
+ },
+ _ => Msg::Nope,
+ });
- html!{
+ html! {
<>
<main>
<section class="hero">
@@ -502,9 +471,9 @@ impl Component for MainView {
{
for self.name_links.iter().map(|link|
html!{
- <NameView weak_link=link
+ <NameView weak_link=link
generated=self.link.callback(
- |n: Name|
+ |n: Name|
Msg::GeneratedName(n)
)
/>
@@ -574,7 +543,7 @@ impl Component for MainView {
<option value="qrcode">{ "QR Code" }</option>
</select>
</div>
-
+
{ self.render_download() }
</div>
@@ -601,7 +570,7 @@ impl Component for MainView {
impl MainView {
fn render_error(&self) -> Html {
- html!{
+ html! {
<>
{
match &self.error {
@@ -622,13 +591,13 @@ impl MainView {
if self.download.is_some() {
let download = self.download.as_ref().unwrap();
- html!{
+ html! {
<a href=download.as_data_link() download=download.file_name class="button is-success level-item" >
{ "Download" }
</a>
}
} else {
- html!{}
+ html! {}
}
}
fn render_preview(&self) -> Html {
@@ -636,53 +605,71 @@ impl MainView {
let download = self.download.as_ref().unwrap();
match download.mime_type {
- MimeType::PDF => html!{
+ MimeType::PDF => html! {
<iframe src=download.as_data_link() alt="PDF Preview" width="400" height="550"/>
},
MimeType::VCard => {
- html!{
+ html! {
<pre>
<code> { download.content.clone() } </code>
</pre>
}
}
- MimeType::SVG => html!{
+ MimeType::SVG => html! {
<img src=download.as_data_link() alt="Image Preview" class="image is-square" width="300" height="300"/>
},
}
} else {
- html!{}
+ html! {}
}
}
- fn generate_pdf(&self) -> Result<String, ()>{
- let regular_bytes = include_bytes!("/usr/share/fonts/liberation/LiberationSans-Regular.ttf");
- let regular_font_data = fonts::FontData::new(regular_bytes.to_vec(), Some(printpdf::BuiltinFont::Helvetica)).expect("font data should be correct");
+ fn generate_pdf(&self) -> Result<String, ()> {
+ let regular_bytes =
+ include_bytes!("/usr/share/fonts/liberation/LiberationSans-Regular.ttf");
+ let regular_font_data = fonts::FontData::new(
+ regular_bytes.to_vec(),
+ Some(printpdf::BuiltinFont::Helvetica),
+ )
+ .expect("font data should be correct");
let bold_bytes = include_bytes!("/usr/share/fonts/liberation/LiberationSans-Bold.ttf");
- let bold_font_data = fonts::FontData::new(bold_bytes.to_vec(), Some(printpdf::BuiltinFont::HelveticaBold)).expect("font data should be correct");
+ let bold_font_data = fonts::FontData::new(
+ bold_bytes.to_vec(),
+ Some(printpdf::BuiltinFont::HelveticaBold),
+ )
+ .expect("font data should be correct");
let italic_bytes = include_bytes!("/usr/share/fonts/liberation/LiberationSans-Italic.ttf");
- let italic_font_data = fonts::FontData::new(italic_bytes.to_vec(), Some(printpdf::BuiltinFont::HelveticaOblique)).expect("font data should be correct");
-
- let bold_italic_bytes = include_bytes!("/usr/share/fonts/liberation/LiberationSans-BoldItalic.ttf");
- let bold_italic_font_data = fonts::FontData::new(bold_italic_bytes.to_vec(), Some(printpdf::BuiltinFont::HelveticaBoldOblique)).expect("font data should be correct");
-
- let font_family = fonts::FontFamily{
- regular: regular_font_data,
- bold: bold_font_data,
- italic: italic_font_data,
- bold_italic: bold_italic_font_data
+ let italic_font_data = fonts::FontData::new(
+ italic_bytes.to_vec(),
+ Some(printpdf::BuiltinFont::HelveticaOblique),
+ )
+ .expect("font data should be correct");
+
+ let bold_italic_bytes =
+ include_bytes!("/usr/share/fonts/liberation/LiberationSans-BoldItalic.ttf");
+ let bold_italic_font_data = fonts::FontData::new(
+ bold_italic_bytes.to_vec(),
+ Some(printpdf::BuiltinFont::HelveticaBoldOblique),
+ )
+ .expect("font data should be correct");
+
+ let font_family = fonts::FontFamily {
+ regular: regular_font_data,
+ bold: bold_font_data,
+ italic: italic_font_data,
+ bold_italic: bold_italic_font_data,
};
let mut doc = genpdf::Document::new(font_family);
doc.set_title("BCard test");
doc.set_minimal_conformance();
-
+
let mut decorator = genpdf::SimplePageDecorator::new();
decorator.set_margins(10);
doc.set_page_decorator(decorator);
-
+
doc.set_line_spacing(1.25);
doc.push(
@@ -704,9 +691,9 @@ impl MainView {
}
fn get_subcomponent_count(&self) -> usize {
self.name_links.len()
- + self.address_links.len()
- + self.telephone_links.len()
- + self.dates_links.len()
- + self.organizational_links.len()
+ + self.address_links.len()
+ + self.telephone_links.len()
+ + self.dates_links.len()
+ + self.organizational_links.len()
}
-} \ No newline at end of file
+}
diff --git a/src/view/mod.rs b/src/view/mod.rs
index 0751c53..cbff0fd 100644
--- a/src/view/mod.rs
+++ b/src/view/mod.rs
@@ -1,27 +1,30 @@
-use yew::prelude::*;
+use crate::viewmodel::*;
use std::cell::RefCell;
use std::ops::Deref;
use std::rc::Rc;
-use crate::viewmodel::*;
+use yew::prelude::*;
-pub mod main;
-pub mod name;
pub mod address;
-pub mod telephone;
pub mod dates;
+pub mod main;
+pub mod name;
pub mod organizational;
+pub mod telephone;
#[derive(Clone, PartialEq, Properties)]
-pub struct InputProps<O, C>
- where O: VCardPropertyInputObject<C> + Clone,
- C: VCardPropertyInputComponent<O> + Clone
+pub struct InputProps<O, C>
+where
+ O: VCardPropertyInputObject<C> + Clone,
+ C: VCardPropertyInputComponent<O> + Clone,
{
pub generated: Callback<O>,
pub weak_link: WeakComponentLink<C>,
}
/// Trait for types that represent an input component for a vcard property.
-pub trait VCardPropertyInputComponent<T: VCardPropertyInputObject<Self>>: Component + Clone + PartialEq {
+pub trait VCardPropertyInputComponent<T: VCardPropertyInputObject<Self>>:
+ Component + Clone + PartialEq
+{
/// Returns the object containing the input data.
fn get_input_object(&self) -> T;
/// Getter function for the title of the component
@@ -30,7 +33,7 @@ pub trait VCardPropertyInputComponent<T: VCardPropertyInputObject<Self>>: Compon
fn get_error(&self) -> Option<Error>;
/// Returns the error as `Html`
fn render_error(&self) -> Html {
- html!{
+ html! {
<>
{
if self.get_error().is_some() {
@@ -75,4 +78,4 @@ impl<COMP: Component> PartialEq for WeakComponentLink<COMP> {
fn eq(&self, other: &Self) -> bool {
Rc::ptr_eq(&self.0, &other.0)
}
-} \ No newline at end of file
+}
diff --git a/src/view/name.rs b/src/view/name.rs
index 4976e7d..4b7089b 100644
--- a/src/view/name.rs
+++ b/src/view/name.rs
@@ -1,28 +1,28 @@
+use super::VCardPropertyInputComponent;
use crate::view::InputProps;
-use yew::prelude::*;
-use yewtil::NeqAssign;
-use crate::viewmodel::Error;
use crate::viewmodel::name::*;
+use crate::viewmodel::Error;
use crate::viewmodel::VCardPropertyInputObject;
-use super::VCardPropertyInputComponent;
+use yew::prelude::*;
+use yewtil::NeqAssign;
-type Props = InputProps<Name,NameView>;
+type Props = InputProps<Name, NameView>;
/// View Component for a `name` field
-///
+///
/// # Examples
-///
+///
/// ```compile_fail
/// let html = html!{
-/// <NameView weak_link=some_weak_component_link
+/// <NameView weak_link=some_weak_component_link
/// generated=self.link.callback(
-/// |n: Irc<Name>|
+/// |n: Irc<Name>|
/// Msg::GeneratedName(some_name)
/// )
/// />
/// };
/// ```
-#[derive(Clone,PartialEq)]
+#[derive(Clone, PartialEq)]
pub struct NameView {
props: Props,
value: Name,
@@ -71,17 +71,17 @@ impl Component for NameView {
Msg::UpdateSuffix(s) => self.value.suffix = s,
Msg::Generate => {
self.props.generated.emit(self.value.clone());
- },
+ }
};
true
}
- fn change(&mut self, props: <Self as yew::Component>::Properties) -> bool {
+ fn change(&mut self, props: <Self as yew::Component>::Properties) -> bool {
self.props.neq_assign(props)
}
fn view(&self) -> yew::virtual_dom::VNode {
let link = self.props.weak_link.borrow().clone().unwrap();
- html!{
+ html! {
<div class="box">
{ self.render_error() }
@@ -92,4 +92,4 @@ impl Component for NameView {
</div>
}
}
-} \ No newline at end of file
+}
diff --git a/src/view/organizational.rs b/src/view/organizational.rs
index e6636ec..7f2ca69 100644
--- a/src/view/organizational.rs
+++ b/src/view/organizational.rs
@@ -1,15 +1,15 @@
-use crate::viewmodel::utility::File;
-use yew::prelude::*;
-use yewtil::NeqAssign;
-use crate::viewmodel::Error;
+use super::VCardPropertyInputComponent;
use crate::view::InputProps;
use crate::viewmodel::organizational::*;
+use crate::viewmodel::utility::File;
+use crate::viewmodel::Error;
use crate::viewmodel::VCardPropertyInputObject;
-use super::VCardPropertyInputComponent;
+use yew::prelude::*;
+use yewtil::NeqAssign;
-type Props = InputProps<Organizational,OrganizationalView>;
+type Props = InputProps<Organizational, OrganizationalView>;
-#[derive(Clone,PartialEq)]
+#[derive(Clone, PartialEq)]
pub struct OrganizationalView {
props: Props,
value: Organizational,
@@ -60,7 +60,7 @@ impl Component for OrganizationalView {
Msg::UpdateRelated(r) => self.value.related = r,
Msg::Generate => {
self.props.generated.emit(self.value.clone());
- },
+ }
};
true
}
@@ -70,7 +70,7 @@ impl Component for OrganizationalView {
fn view(&self) -> yew::virtual_dom::VNode {
let link = self.props.weak_link.borrow().clone().unwrap();
- html!{
+ html! {
<div class="box">
{ self.render_error() }
@@ -81,4 +81,4 @@ impl Component for OrganizationalView {
</div>
}
}
-} \ No newline at end of file
+}
diff --git a/src/view/telephone.rs b/src/view/telephone.rs
index dc93632..68389ba 100644
--- a/src/view/telephone.rs
+++ b/src/view/telephone.rs
@@ -1,28 +1,28 @@
+use super::VCardPropertyInputComponent;
use crate::view::InputProps;
-use yew::prelude::*;
-use yewtil::NeqAssign;
-use crate::viewmodel::Error;
use crate::viewmodel::telephone::*;
+use crate::viewmodel::Error;
use crate::viewmodel::VCardPropertyInputObject;
-use super::VCardPropertyInputComponent;
+use yew::prelude::*;
+use yewtil::NeqAssign;
-type Props = InputProps<Telephone,TelephoneView>;
+type Props = InputProps<Telephone, TelephoneView>;
/// View Component for a `telephone` field
-///
+///
/// # Examples
-///
+///
/// ```compile_fail
/// let html = html!{
-/// <TelephoneView weak_link=some_weak_component_link
+/// <TelephoneView weak_link=some_weak_component_link
/// generated=self.link.callback(
-/// |n: Irc<Telephone>|
+/// |n: Irc<Telephone>|
/// Msg::GeneratedTelephone(some_telephone)
/// )
/// />
/// };
/// ```
-#[derive(Clone,PartialEq)]
+#[derive(Clone, PartialEq)]
pub struct TelephoneView {
props: Props,
value: Telephone,
@@ -85,13 +85,13 @@ impl Component for TelephoneView {
};
true
}
- fn change(&mut self, props: <Self as yew::Component>::Properties) -> bool {
+ fn change(&mut self, props: <Self as yew::Component>::Properties) -> bool {
self.props.neq_assign(props)
}
fn view(&self) -> yew::virtual_dom::VNode {
let link = self.props.weak_link.borrow().clone().unwrap();
- html!{
+ html! {
<div class="box">
{ self.render_error() }
@@ -102,4 +102,4 @@ impl Component for TelephoneView {
</div>
}
}
-} \ No newline at end of file
+}
diff --git a/src/viewmodel/address.rs b/src/viewmodel/address.rs
index 71cc8d3..9542675 100644
--- a/src/viewmodel/address.rs
+++ b/src/viewmodel/address.rs
@@ -31,15 +31,15 @@ impl VCardPropertyInputObject<AddressView> for Address {
fn get_input_fields(&self, link: &ComponentLink<AddressView>) -> Vec<VCardPropertyInputField> {
let typ = String::from("text");
vec![
- VCardPropertyInputField::Text{
+ VCardPropertyInputField::Text {
label: "Post Office Box".to_string(),
id: Some("post_office_box".to_string()),
placeholder: None,
oninput: link.callback(|e: InputData| Msg::UpdatePostOfficeBox(e.value)),
value: self.post_office_box.clone(),
- typ: typ.clone(),
+ typ: typ.clone(),
},
- VCardPropertyInputField::Text{
+ VCardPropertyInputField::Text {
label: "Extension".to_string(),
id: Some("extension".to_string()),
placeholder: None,
@@ -47,7 +47,7 @@ impl VCardPropertyInputObject<AddressView> for Address {
value: self.extension.clone(),
typ: typ.clone(),
},
- VCardPropertyInputField::Text{
+ VCardPropertyInputField::Text {
label: "Street".to_string(),
id: Some("street".to_string()),
placeholder: None,
@@ -55,7 +55,7 @@ impl VCardPropertyInputObject<AddressView> for Address {
value: self.street.clone(),
typ: typ.clone(),
},
- VCardPropertyInputField::Text{
+ VCardPropertyInputField::Text {
label: "Locality".to_string(),
id: Some("locality".to_string()),
placeholder: None,
@@ -63,7 +63,7 @@ impl VCardPropertyInputObject<AddressView> for Address {
value: self.locality.clone(),
typ: typ.clone(),
},
- VCardPropertyInputField::Text{
+ VCardPropertyInputField::Text {
label: "Region".to_string(),
id: Some("region".to_string()),
placeholder: None,
@@ -71,7 +71,7 @@ impl VCardPropertyInputObject<AddressView> for Address {
value: self.region.clone(),
typ: typ.clone(),
},
- VCardPropertyInputField::Text{
+ VCardPropertyInputField::Text {
label: "Code".to_string(),
id: Some("code".to_string()),
placeholder: None,
@@ -79,7 +79,7 @@ impl VCardPropertyInputObject<AddressView> for Address {
value: self.code.clone(),
typ: typ.clone(),
},
- VCardPropertyInputField::Text{
+ VCardPropertyInputField::Text {
label: "Country".to_string(),
id: Some("country".to_string()),
placeholder: None,
@@ -87,13 +87,13 @@ impl VCardPropertyInputObject<AddressView> for Address {
value: self.country.clone(),
typ,
},
- VCardPropertyInputField::CheckBox{
+ VCardPropertyInputField::CheckBox {
label: "Work".to_string(),
id: Some("work".to_string()),
onclick: link.callback(|_: MouseEvent| Msg::ToggleWork),
value: self.work,
},
- VCardPropertyInputField::CheckBox{
+ VCardPropertyInputField::CheckBox {
label: "Home".to_string(),
id: Some("home".to_string()),
onclick: link.callback(|_: MouseEvent| Msg::ToggleHome),
@@ -102,12 +102,12 @@ impl VCardPropertyInputObject<AddressView> for Address {
]
}
fn is_empty(&self) -> bool {
- self.post_office_box.is_empty() &&
- self.extension.is_empty() &&
- self.street.is_empty() &&
- self.locality.is_empty() &&
- self.region.is_empty() &&
- self.code.is_empty() &&
- self.country.is_empty()
+ self.post_office_box.is_empty()
+ && self.extension.is_empty()
+ && self.street.is_empty()
+ && self.locality.is_empty()
+ && self.region.is_empty()
+ && self.code.is_empty()
+ && self.country.is_empty()
}
-} \ No newline at end of file
+}
diff --git a/src/viewmodel/dates.rs b/src/viewmodel/dates.rs
index 28e8bad..7d8d394 100644
--- a/src/viewmodel/dates.rs
+++ b/src/viewmodel/dates.rs
@@ -1,5 +1,5 @@
-use crate::view::dates::*;
use super::*;
+use crate::view::dates::*;
/// Type that represents the vcard `anniversary` and `birthday` properties.
#[derive(Clone, Debug, PartialEq)]
@@ -15,10 +15,13 @@ impl VCardPropertyInputObject<DatesView> for Dates {
birthday: String::new(),
}
}
- fn get_input_fields(&self, link: &yew::html::Scope<DatesView>) -> std::vec::Vec<VCardPropertyInputField> {
+ fn get_input_fields(
+ &self,
+ link: &yew::html::Scope<DatesView>,
+ ) -> std::vec::Vec<VCardPropertyInputField> {
let typ = String::from("date");
vec![
- VCardPropertyInputField::Text{
+ VCardPropertyInputField::Text {
label: "Anniversary".to_string(),
id: Some("anniversary".to_string()),
placeholder: None,
@@ -26,7 +29,7 @@ impl VCardPropertyInputObject<DatesView> for Dates {
value: self.anniversary.clone(),
typ: typ.clone(),
},
- VCardPropertyInputField::Text{
+ VCardPropertyInputField::Text {
label: "Birthday".to_string(),
id: Some("birthday".to_string()),
placeholder: None,
@@ -37,7 +40,6 @@ impl VCardPropertyInputObject<DatesView> for Dates {
]
}
fn is_empty(&self) -> bool {
- self.anniversary.is_empty()
- && self.birthday.is_empty()
+ self.anniversary.is_empty() && self.birthday.is_empty()
}
-} \ No newline at end of file
+}
diff --git a/src/viewmodel/mod.rs b/src/viewmodel/mod.rs
index 044dbad..0385c61 100644
--- a/src/viewmodel/mod.rs
+++ b/src/viewmodel/mod.rs
@@ -1,23 +1,24 @@
+use crate::view::VCardPropertyInputComponent;
+use crate::viewmodel::utility::File;
use wasm_bindgen::closure::Closure;
-use web_sys::FileReader;
use wasm_bindgen::JsCast;
-use yew::services::ConsoleService;
-use crate::viewmodel::utility::File;
+use web_sys::FileReader;
use yew::prelude::*;
-use crate::view::VCardPropertyInputComponent;
+use yew::services::ConsoleService;
-pub mod vcard;
-pub mod utility;
pub mod address;
-pub mod name;
-pub mod telephone;
pub mod dates;
+pub mod name;
pub mod organizational;
-
+pub mod telephone;
+pub mod utility;
+pub mod vcard;
/// Trait for types that represent the data of a vcard property used inside of a `VCardPropertyInputComponent`.
-pub trait VCardPropertyInputObject<C: VCardPropertyInputComponent<Self>>: Clone + PartialEq
- where Self: Sized
+pub trait VCardPropertyInputObject<C: VCardPropertyInputComponent<Self>>:
+ Clone + PartialEq
+where
+ Self: Sized,
{
/// Function for creating a new (and empty) `VCardPropertyInputObject`.
fn new() -> Self;
@@ -25,12 +26,12 @@ pub trait VCardPropertyInputObject<C: VCardPropertyInputComponent<Self>>: Clone
fn get_input_fields(&self, link: &ComponentLink<C>) -> Vec<VCardPropertyInputField>;
/// Returns a `Html` representation of the `VCardPropertyInputObject`.
fn render(&self, link: &ComponentLink<C>) -> Html {
- html!{
+ html! {
<div class="columns is-mobile is-multiline">
- {
+ {
for self.get_input_fields(link).iter().map(|field|
field.render()
- )
+ )
}
</div>
}
@@ -40,9 +41,9 @@ pub trait VCardPropertyInputObject<C: VCardPropertyInputComponent<Self>>: Clone
}
/// Type for saving error messages.
-///
+///
/// More of a placeholder for something better later on.
-#[derive(Debug,Clone,PartialEq)]
+#[derive(Debug, Clone, PartialEq)]
pub struct Error {
pub msg: String,
}
@@ -97,10 +98,16 @@ impl VCardPropertyInputField {
} => Self::checkbox_field_input(label, id, value, onclick),
}
}
- /// Returns an `Html` representation of a text input field with the given parameters.
- fn text_field_input(label: &str, id: &Option<String>, placeholder: &Option<String>, oninput: &Callback<InputData>, typ: &str) -> Html {
- html!{
- <div class="field column
+ /// Returns an `Html` representation of a text input field with the given parameters.
+ fn text_field_input(
+ label: &str,
+ id: &Option<String>,
+ placeholder: &Option<String>,
+ oninput: &Callback<InputData>,
+ typ: &str,
+ ) -> Html {
+ html! {
+ <div class="field column
is-one-fifth-widescreen
is-one-quarter-desktop
is-one-third-tablet
@@ -116,14 +123,19 @@ impl VCardPropertyInputField {
</div>
}
}
- /// Returns an `Html` representation of a file input field with the given parameters.
- fn file_field_input(label: &str, name: &str, callback: &Callback<Option<File>>, file: &Option<File>) -> Html {
+ /// Returns an `Html` representation of a file input field with the given parameters.
+ fn file_field_input(
+ label: &str,
+ name: &str,
+ callback: &Callback<Option<File>>,
+ file: &Option<File>,
+ ) -> Html {
let callback = callback.clone();
let onchange = Callback::<()>::default();
- let onchange = onchange.reform(move |c: ChangeData|
+ let onchange = onchange.reform(move |c: ChangeData| {
if let ChangeData::Files(files) = c {
match files.item(0) {
- Some(file) => {
+ Some(file) => {
let file_reader = FileReader::new().unwrap();
match file_reader.read_as_data_url(&file) {
Ok(_) => (),
@@ -131,33 +143,33 @@ impl VCardPropertyInputField {
};
let callback = callback.clone();
- let onload = Closure::wrap(Box::new(move |event: Event|{
- let file_reader: FileReader = event.target().unwrap().dyn_into().unwrap();
- let data_url: Option<String> = file_reader.result().unwrap().as_string();
+ let onload = Closure::wrap(Box::new(move |event: Event| {
+ let file_reader: FileReader =
+ event.target().unwrap().dyn_into().unwrap();
+ let data_url: Option<String> =
+ file_reader.result().unwrap().as_string();
match data_url {
- Some(content) => callback.emit(
- Some(File {
- name: file.name(),
- content,
- })
- ),
+ Some(content) => callback.emit(Some(File {
+ name: file.name(),
+ content,
+ })),
None => {
ConsoleService::warn("Couldn't get data url as string.");
callback.emit(None);
- },
+ }
};
}) as Box<dyn FnMut(_)>);
file_reader.set_onload(Some(onload.as_ref().unchecked_ref()));
onload.forget();
- },
+ }
None => callback.emit(None),
}
} else {
callback.emit(None);
}
- );
- html!{
+ });
+ html! {
<div class="field column
is-one-fifth-widescreen
is-one-quarter-desktop
@@ -192,17 +204,22 @@ impl VCardPropertyInputField {
</div>
}
}
- /// Returns an `Html` representation of a checkbox input field with the given parameters.
- fn checkbox_field_input(label: &str, id: &Option<String>, checked: &bool, onclick: &Callback<MouseEvent>) -> Html {
- html!{
- <div class="field column
+ /// Returns an `Html` representation of a checkbox input field with the given parameters.
+ fn checkbox_field_input(
+ label: &str,
+ id: &Option<String>,
+ checked: &bool,
+ onclick: &Callback<MouseEvent>,
+ ) -> Html {
+ html! {
+ <div class="field column
is-one-fifth-widescreen
is-one-quarter-desktop
is-one-third-tablet
is-half-mobile" >
<label class="checkbox">
<input id=id.as_ref().unwrap_or(&"".to_string())
- type="checkbox"
+ type="checkbox"
checked=*checked
onclick=onclick
/>
@@ -211,4 +228,4 @@ impl VCardPropertyInputField {
</div>
}
}
-} \ No newline at end of file
+}
diff --git a/src/viewmodel/name.rs b/src/viewmodel/name.rs
index ee4736f..de0aa81 100644
--- a/src/viewmodel/name.rs
+++ b/src/viewmodel/name.rs
@@ -2,7 +2,7 @@ use super::*;
use crate::view::name::*;
/// Type that represents a vcard `name` property
-///
+///
/// # Examples
/// ```
/// # use bcard_wasm_webapp::viewmodel::name::Name;
@@ -13,7 +13,7 @@ use crate::view::name::*;
/// name.middle_name = String::from("Charles");
/// name.last_name = String::from("Clarke");
/// name.suffix = String::from("CBE FRAS");
-///
+///
/// assert_eq!(name.generate_fn(), String::from("Sir Arthur Charles Clarke, CBE FRAS"));
/// ```
#[derive(Clone, Debug, PartialEq)]
@@ -35,10 +35,13 @@ impl VCardPropertyInputObject<NameView> for Name {
suffix: String::new(),
}
}
- fn get_input_fields(&self, link: &ComponentLink<NameView>) -> std::vec::Vec<VCardPropertyInputField> {
+ fn get_input_fields(
+ &self,
+ link: &ComponentLink<NameView>,
+ ) -> std::vec::Vec<VCardPropertyInputField> {
let typ = String::from("text");
vec![
- VCardPropertyInputField::Text{
+ VCardPropertyInputField::Text {
label: "Prefix".to_string(),
id: Some("prefix".to_string()),
placeholder: Some("Sir".to_string()),
@@ -46,7 +49,7 @@ impl VCardPropertyInputObject<NameView> for Name {
value: self.prefix.clone(),
typ: typ.clone(),
},
- VCardPropertyInputField::Text{
+ VCardPropertyInputField::Text {
label: "First Name".to_string(),
id: Some("first_name".to_string()),
placeholder: Some("Arthur".to_string()),
@@ -54,7 +57,7 @@ impl VCardPropertyInputObject<NameView> for Name {
value: self.first_name.clone(),
typ: typ.clone(),
},
- VCardPropertyInputField::Text{
+ VCardPropertyInputField::Text {
label: "Middle Name".to_string(),
id: Some("middle_name".to_string()),
placeholder: Some("Charles".to_string()),
@@ -62,7 +65,7 @@ impl VCardPropertyInputObject<NameView> for Name {
value: self.middle_name.clone(),
typ: typ.clone(),
},
- VCardPropertyInputField::Text{
+ VCardPropertyInputField::Text {
label: "Last Name".to_string(),
id: Some("last_name".to_string()),
placeholder: Some("Clarke".to_string()),
@@ -70,7 +73,7 @@ impl VCardPropertyInputObject<NameView> for Name {
value: self.last_name.clone(),
typ: typ.clone(),
},
- VCardPropertyInputField::Text{
+ VCardPropertyInputField::Text {
label: "Suffix".to_string(),
id: Some("suffix".to_string()),
placeholder: Some("CBE FRAS".to_string()),
@@ -81,11 +84,11 @@ impl VCardPropertyInputObject<NameView> for Name {
]
}
fn is_empty(&self) -> bool {
- self.prefix.is_empty() &&
- self.first_name.is_empty() &&
- self.middle_name.is_empty() &&
- self.last_name.is_empty() &&
- self.suffix.is_empty()
+ self.prefix.is_empty()
+ && self.first_name.is_empty()
+ && self.middle_name.is_empty()
+ && self.last_name.is_empty()
+ && self.suffix.is_empty()
}
}
@@ -113,4 +116,4 @@ impl Name {
full_name
}
-} \ No newline at end of file
+}
diff --git a/src/viewmodel/organizational.rs b/src/viewmodel/organizational.rs
index c8f7164..72b19d2 100644
--- a/src/viewmodel/organizational.rs
+++ b/src/viewmodel/organizational.rs
@@ -1,7 +1,7 @@
-use crate::view::organizational::*;
use super::*;
+use crate::view::organizational::*;
-#[derive(Clone,Debug,PartialEq)]
+#[derive(Clone, Debug, PartialEq)]
pub struct Organizational {
pub org: String,
pub logo: Option<File>,
@@ -22,10 +22,13 @@ impl VCardPropertyInputObject<OrganizationalView> for Organizational {
related: String::new(),
}
}
- fn get_input_fields(&self, link: &yew::html::Scope<OrganizationalView>) -> std::vec::Vec<VCardPropertyInputField> {
+ fn get_input_fields(
+ &self,
+ link: &yew::html::Scope<OrganizationalView>,
+ ) -> std::vec::Vec<VCardPropertyInputField> {
let typ = String::from("text");
vec![
- VCardPropertyInputField::Text{
+ VCardPropertyInputField::Text {
label: "Organisation".to_string(),
id: Some("org".to_string()),
placeholder: None,
@@ -33,46 +36,14 @@ impl VCardPropertyInputObject<OrganizationalView> for Organizational {
value: self.org.clone(),
typ: typ.clone(),
},
- VCardPropertyInputField::File{ // TODO: Add Upload for logo
+ VCardPropertyInputField::File {
+ // TODO: Add Upload for logo
label: "Logo".to_string(),
name: "logo".to_string(),
- callback: link.callback(|file: Option<File>|
- /*
- if let ChangeData::Files(files) = c {
- match files.item(0) {
- Some(file) => {
- let filereader = match FileReaderSync::new() {
- Ok(reader) => reader,
- Err(_) => {
- ConsoleService::warn("Couldn't create new filereader.");
- return Msg::UpdateLogo(None)
- },
- };
- let content = match filereader.read_as_data_url(&file) {
- Ok(content) => content,
- Err(_) => {
- ConsoleService::warn("Error: Couldn't get file as data url.");
- return Msg::UpdateLogo(None)
- },
- };
- Msg::UpdateLogo(
- Some(File {
- name: file.name(),
- content,
- })
- )
- },
- None => Msg::UpdateLogo(None),
- }
- } else {
- Msg::UpdateLogo(None)
- }
- */
- Msg::UpdateLogo(file)
- ),
+ callback: link.callback(|file: Option<File>| Msg::UpdateLogo(file)),
value: self.logo.clone(),
},
- VCardPropertyInputField::Text{
+ VCardPropertyInputField::Text {
label: "Title".to_string(),
id: Some("title".to_string()),
placeholder: None,
@@ -80,7 +51,7 @@ impl VCardPropertyInputObject<OrganizationalView> for Organizational {
value: self.title.clone(),
typ: typ.clone(),
},
- VCardPropertyInputField::Text{
+ VCardPropertyInputField::Text {
label: "Role".to_string(),
id: Some("role".to_string()),
placeholder: None,
@@ -88,7 +59,7 @@ impl VCardPropertyInputObject<OrganizationalView> for Organizational {
value: self.role.clone(),
typ: typ.clone(),
},
- VCardPropertyInputField::Text{
+ VCardPropertyInputField::Text {
label: "Member".to_string(),
id: Some("member".to_string()),
placeholder: None,
@@ -96,7 +67,7 @@ impl VCardPropertyInputObject<OrganizationalView> for Organizational {
value: self.member.clone(),
typ: typ.clone(),
},
- VCardPropertyInputField::Text{
+ VCardPropertyInputField::Text {
label: "Related".to_string(),
id: Some("related".to_string()),
placeholder: None,
@@ -107,11 +78,11 @@ impl VCardPropertyInputObject<OrganizationalView> for Organizational {
]
}
fn is_empty(&self) -> bool {
- self.org.is_empty() &&
- self.logo.is_none() &&
- self.title.is_empty() &&
- self.role.is_empty() &&
- self.member.is_empty() &&
- self.related.is_empty()
+ self.org.is_empty()
+ && self.logo.is_none()
+ && self.title.is_empty()
+ && self.role.is_empty()
+ && self.member.is_empty()
+ && self.related.is_empty()
}
-} \ No newline at end of file
+}
diff --git a/src/viewmodel/telephone.rs b/src/viewmodel/telephone.rs
index ee616c3..44b938f 100644
--- a/src/viewmodel/telephone.rs
+++ b/src/viewmodel/telephone.rs
@@ -30,10 +30,13 @@ impl VCardPropertyInputObject<TelephoneView> for Telephone {
text_phone: false,
}
}
- fn get_input_fields(&self, link: &ComponentLink<TelephoneView>) -> Vec<VCardPropertyInputField> {
+ fn get_input_fields(
+ &self,
+ link: &ComponentLink<TelephoneView>,
+ ) -> Vec<VCardPropertyInputField> {
let typ = String::from("tel");
vec![
- VCardPropertyInputField::Text{
+ VCardPropertyInputField::Text {
label: "Number".to_string(),
id: Some("number".to_string()),
placeholder: None,
@@ -41,55 +44,55 @@ impl VCardPropertyInputObject<TelephoneView> for Telephone {
value: self.number.clone(),
typ,
},
- VCardPropertyInputField::CheckBox{
+ VCardPropertyInputField::CheckBox {
label: "Work".to_string(),
id: Some("work".to_string()),
onclick: link.callback(|_: MouseEvent| Msg::ToggleWork),
value: self.work,
},
- VCardPropertyInputField::CheckBox{
+ VCardPropertyInputField::CheckBox {
label: "Home".to_string(),
id: Some("home".to_string()),
onclick: link.callback(|_: MouseEvent| Msg::ToggleHome),
value: self.home,
},
- VCardPropertyInputField::CheckBox{
+ VCardPropertyInputField::CheckBox {
label: "Text".to_string(),
id: Some("text".to_string()),
onclick: link.callback(|_: MouseEvent| Msg::ToggleText),
value: self.text,
},
- VCardPropertyInputField::CheckBox{
+ VCardPropertyInputField::CheckBox {
label: "Voice".to_string(),
id: Some("voice".to_string()),
onclick: link.callback(|_: MouseEvent| Msg::ToggleVoice),
value: self.voice,
},
- VCardPropertyInputField::CheckBox{
+ VCardPropertyInputField::CheckBox {
label: "Fax".to_string(),
id: Some("fax".to_string()),
onclick: link.callback(|_: MouseEvent| Msg::ToggleFax),
value: self.fax,
},
- VCardPropertyInputField::CheckBox{
+ VCardPropertyInputField::CheckBox {
label: "Cell".to_string(),
id: Some("cell".to_string()),
onclick: link.callback(|_: MouseEvent| Msg::ToggleCell),
value: self.cell,
},
- VCardPropertyInputField::CheckBox{
+ VCardPropertyInputField::CheckBox {
label: "Video".to_string(),
id: Some("video".to_string()),
onclick: link.callback(|_: MouseEvent| Msg::ToggleVideo),
value: self.video,
},
- VCardPropertyInputField::CheckBox{
+ VCardPropertyInputField::CheckBox {
label: "Pager".to_string(),
id: Some("pager".to_string()),
onclick: link.callback(|_: MouseEvent| Msg::TogglePager),
value: self.pager,
},
- VCardPropertyInputField::CheckBox{
+ VCardPropertyInputField::CheckBox {
label: "Text Phone".to_string(),
id: Some("text_phone".to_string()),
onclick: link.callback(|_: MouseEvent| Msg::ToggleTextPhone),
@@ -100,4 +103,4 @@ impl VCardPropertyInputObject<TelephoneView> for Telephone {
fn is_empty(&self) -> bool {
self.number.is_empty()
}
-} \ No newline at end of file
+}
diff --git a/src/viewmodel/utility.rs b/src/viewmodel/utility.rs
index cb581ac..617ee45 100644
--- a/src/viewmodel/utility.rs
+++ b/src/viewmodel/utility.rs
@@ -1,5 +1,3 @@
-
-
#[derive(Clone)]
pub struct Download {
pub file_name: String,
@@ -40,8 +38,8 @@ pub enum DownloadOption {
QrCode,
}
-#[derive(Clone,Debug,PartialEq)]
+#[derive(Clone, Debug, PartialEq)]
pub struct File {
pub name: String,
pub content: String,
-} \ No newline at end of file
+}
diff --git a/src/viewmodel/vcard.rs b/src/viewmodel/vcard.rs
index 0d2d6c4..18ce43a 100644
--- a/src/viewmodel/vcard.rs
+++ b/src/viewmodel/vcard.rs
@@ -1,8 +1,8 @@
-use crate::viewmodel::organizational::Organizational;
-use crate::viewmodel::dates::Dates;
-use crate::viewmodel::telephone::Telephone;
use crate::viewmodel::address::Address;
+use crate::viewmodel::dates::Dates;
use crate::viewmodel::name::Name;
+use crate::viewmodel::organizational::Organizational;
+use crate::viewmodel::telephone::Telephone;
/// Type that represents the data structure of a vcard.
#[derive(Clone, Debug)]
@@ -37,4 +37,4 @@ impl VCardData {
make_vec_adder_fn!( fn add_telephone telephones => telephone: Telephone );
make_vec_adder_fn!( fn add_dates datess => dates: Dates );
make_vec_adder_fn!( fn add_organizational organizationals => organizational: Organizational );
-} \ No newline at end of file
+}