summaryrefslogtreecommitdiff
path: root/src/view/main.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/view/main.rs')
-rw-r--r--src/view/main.rs345
1 files changed, 166 insertions, 179 deletions
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
+}