summaryrefslogtreecommitdiff
path: root/src/view
diff options
context:
space:
mode:
Diffstat (limited to 'src/view')
-rw-r--r--src/view/address.rs29
-rw-r--r--src/view/main.rs281
-rw-r--r--src/view/name.rs57
-rw-r--r--src/view/telephone.rs29
4 files changed, 256 insertions, 140 deletions
diff --git a/src/view/address.rs b/src/view/address.rs
index 23b697a..a16d93a 100644
--- a/src/view/address.rs
+++ b/src/view/address.rs
@@ -1,5 +1,9 @@
+use yew::services::ConsoleService;
+use yewtil::ptr::Irc;
+use yewtil::ptr::Mrc;
use super::WeakComponentLink;
use yew::prelude::*;
+use yewtil::NeqAssign;
use crate::viewmodel::address::*;
use crate::viewmodel::VCardPropertyInputObject;
use super::VCardPropertyInputComponent;
@@ -8,7 +12,7 @@ use crate::viewmodel::Error;
pub struct AddressView {
props: Props,
- value: Address,
+ value: Mrc<Address>,
error: Option<Error>,
}
@@ -28,13 +32,19 @@ pub enum Msg {
#[derive(Clone, PartialEq, Properties)]
pub struct Props {
- pub generated: Callback<Address>,
+ pub generated: Callback<Irc<Address>>,
pub weak_link: WeakComponentLink<AddressView>,
}
impl VCardPropertyInputComponent<Address> for AddressView {
fn get_input_object(&self) -> Address {
- self.value.clone()
+ match self.value.irc().try_unwrap() {
+ Ok(address) => address,
+ Err(_) => {
+ ConsoleService::error("Couldn't unwrap address");
+ Address::new()
+ },
+ }
}
fn get_title(&self) -> String {
"Address".to_string()
@@ -51,7 +61,7 @@ impl Component for AddressView {
props.weak_link.borrow_mut().replace(link);
Self {
props,
- value: Address::new(),
+ value: Mrc::new(Address::new()),
error: None,
}
}
@@ -66,19 +76,14 @@ impl Component for AddressView {
Msg::UpdateCountry(c) => self.value.country = c,
Msg::ToggleWork => self.value.work = !self.value.work,
Msg::ToggleHome => self.value.home = !self.value.home,
- Generate => {
- self.props.generated.emit(self.value);
+ Msg::Generate => {
+ self.props.generated.emit(self.value.irc());
},
};
true
}
fn change(&mut self, props: <Self as yew::Component>::Properties) -> bool {
- if self.props != props {
- self.props = props;
- true
- } else {
- false
- }
+ self.props.neq_assign(props)
}
fn view(&self) -> yew::virtual_dom::VNode {
let link = self.props.weak_link.borrow().clone().unwrap();
diff --git a/src/view/main.rs b/src/view/main.rs
index e926504..b1c0dda 100644
--- a/src/view/main.rs
+++ b/src/view/main.rs
@@ -1,6 +1,8 @@
+use yew::services::ConsoleService;
+use yewtil::ptr::Irc;
+use crate::viewmodel::vcard::VCardData;
use crate::viewmodel::Error;
use crate::view::telephone::{self,TelephoneView};
-use std::collections::HashSet;
use super::WeakComponentLink;
use super::name::{self,NameView};
use super::address::{self,AddressView};
@@ -9,13 +11,15 @@ use genpdf::{elements, style, fonts};
use qrcodegen::QrCode;
use qrcodegen::QrCodeEcc;
use yew::prelude::*;
-use vobject::Vcard;
+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 {
@@ -23,7 +27,7 @@ pub struct MainView {
error: Option<Error>,
download: Option<Download>,
selected_option: DownloadOption,
- vcard_builder: VcardBuilder,
+ vcard_data: Mrc<VCardData>,
name_links: Vec<WeakComponentLink<NameView>>,
address_links: Vec<WeakComponentLink<AddressView>>,
@@ -40,10 +44,9 @@ pub enum Msg {
ChangeDownloadOption(DownloadOption),
Generate,
- GeneratedFormattedName(String),
- GeneratedName(Name),
- GeneratedAddress(Address),
- GeneratedTelephone(Telephone),
+ GeneratedName(Irc<Name>),
+ GeneratedAddress(Irc<Address>),
+ GeneratedTelephone(Irc<Telephone>),
GenerationComplete,
Nope,
@@ -59,7 +62,7 @@ impl Component for MainView {
error: None,
download: None,
selected_option: DownloadOption::VCard,
- vcard_builder: VcardBuilder::new(),
+ vcard_data: Mrc::new(VCardData::new()),
name_links: vec![WeakComponentLink::default()],
address_links: vec![WeakComponentLink::default()],
@@ -126,26 +129,14 @@ impl Component for MainView {
shouldrender = true;
},
- Msg::GeneratedFormattedName(formatted_name) => {
-
- self.answer_count += 1;
-
- self.vcard_builder = self.vcard_builder.with_fullname(formatted_name);
-
- shouldrender = true;
- },
Msg::GeneratedName(name) => {
self.answer_count += 1;
- self.vcard_builder = self.vcard_builder.with_name(
- parameters!(),
- name.last_name.is_empty().then(|| name.last_name),
- name.first_name.is_empty().then(|| name.first_name),
- name.middle_name.is_empty().then(|| name.middle_name),
- name.prefix.is_empty().then(|| name.prefix),
- name.suffix.is_empty().then(|| name.suffix)
- );
+ 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"),
+ };
shouldrender = true;
@@ -154,9 +145,10 @@ impl Component for MainView {
self.answer_count += 1;
- self.vcard_builder = self.vcard_builder.with_adr(
- parameters!(),
- );
+ 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"),
+ };
shouldrender = true;
},
@@ -164,31 +156,10 @@ impl Component for MainView {
self.answer_count += 1;
- match telephone {
- Ok(telephone) => {
- match self.vcard {
- Some(vcard) => {
- match vcard.telephones {
- Some(telephones) => {
- telephones.insert(telephone);
- },
- None => {
- let telephones = {
- let mut telephones = HashSet::new();
- telephones.insert(telephone);
-
- telephones
- };
-
- vcard.telephones = Some(vcard::Set::from_hash_set(telephones).unwrap());
- }
- };
- },
- None => (),
- };
- },
- Err(_) => (),
- }
+ 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"),
+ };
shouldrender = true;
},
@@ -196,43 +167,167 @@ impl Component for MainView {
self.answer_count = 0;
- match self.vcard.clone() {
- Some(vcard) => {
- match self.selected_option {
- DownloadOption::VCard => {
- self.download = Some(
- Download {
- file_name: String::from("VCard.vcs"),
- content: vcard.to_string(),
- mime_type: MimeType::VCard,
- }
- );
- },
- DownloadOption::QrCode => {
- match QrCode::encode_text(&vcard.to_string(), 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!"),
- }
- ),
- };
- },
- _ => (),
- };
-
- self.vcard = None;
- shouldrender = true;
+ let vcard_data = match self.vcard_data.irc().try_unwrap() {
+ Ok(data) => data,
+ Err(err) => {
+ ConsoleService::error(&format!("Error when unwrapping VCardData: {:?}", err));
+ VCardData::new()
},
- None => shouldrender = false, // what TODO here?
+ };
+
+ let mut builder = VcardBuilder::new();
+
+ for name in vcard_data.names {
+
+ 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())
+ );
+ }
+
+ for address in vcard_data.addresses {
+ let mut types = String::new();
+ if address.work {
+ types.push_str("WORK");
+ }
+ if address.home {
+ if types.is_empty() {
+ types.push(',');
+ }
+ types.push_str("HOME")
+ }
+
+ builder = builder.with_adr(
+ parameters!("TYPE" => types),
+ 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()),
+ );
}
+ for telephone in vcard_data.telephones {
+ let mut types = String::new();
+ if telephone.work {
+ types.push_str("WORK");
+ }
+ if telephone.home {
+ if types.is_empty() {
+ types.push(',');
+ }
+ types.push_str("HOME")
+ }
+ if telephone.text {
+ if types.is_empty() {
+ types.push(',');
+ }
+ types.push_str("TEXT")
+ }
+ if telephone.voice {
+ if types.is_empty() {
+ types.push(',');
+ }
+ types.push_str("VOICE")
+ }
+ if telephone.fax {
+ if types.is_empty() {
+ types.push(',');
+ }
+ types.push_str("FAX")
+ }
+ if telephone.cell {
+ if types.is_empty() {
+ types.push(',');
+ }
+ types.push_str("CELL")
+ }
+ if telephone.video {
+ if types.is_empty() {
+ types.push(',');
+ }
+ types.push_str("VIDEO")
+ }
+ if telephone.pager {
+ if types.is_empty() {
+ types.push(',');
+ }
+ types.push_str("PAGER")
+ }
+ if telephone.text_phone {
+ if types.is_empty() {
+ types.push(',');
+ }
+ types.push_str("TEXTPHONE")
+ }
+
+ builder = builder.with_tel(
+ parameters!("TYPE" => types),
+ telephone.number.clone(),
+ );
+ }
+
+
+ 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(),
+ }
+ ),
+ };
+
+ match self.vcard_data.get_mut() {
+ Some(vcard_data) => *vcard_data = VCardData::new(),
+ None => ConsoleService::info("Couldn't reset VCardData"),
+ };
+
+ shouldrender = true;
+
},
Msg::Nope => shouldrender = false,
};
@@ -286,12 +381,8 @@ impl Component for MainView {
for self.name_links.iter().map(|link|
html!{
<NameView weak_link=link
- generated_fn=self.link.callback(
- |fmn: Result<properties::FormattedName,()>|
- Msg::GeneratedFormattedName(fmn)
- )
- generated_name=self.link.callback(
- |n: Result<properties::Name,()>|
+ generated=self.link.callback(
+ |n: Irc<Name>|
Msg::GeneratedName(n)
)
/>
@@ -304,7 +395,7 @@ impl Component for MainView {
html!{
<AddressView weak_link=link
generated=self.link.callback(
- |a: Result<properties::Address,()>|
+ |a: Irc<Address>|
Msg::GeneratedAddress(a)
)
/>
@@ -317,7 +408,7 @@ impl Component for MainView {
html!{
<TelephoneView weak_link=link
generated=self.link.callback(
- |t: Result<properties::Telephone,()>|
+ |t: Irc<Telephone>|
Msg::GeneratedTelephone(t)
)
/>
@@ -326,7 +417,7 @@ impl Component for MainView {
}
<div class="block level-left">
- <button onclick=self.link.callback(|_| Msg::Generate) class="button is-primary level-item" />
+ <button onclick=self.link.callback(|_| Msg::Generate) class="button is-primary level-item">{ "Generate" }</button>
<div class="select level-item">
<select id="download_options" onchange=download_options>
diff --git a/src/view/name.rs b/src/view/name.rs
index bee9256..5b64bae 100644
--- a/src/view/name.rs
+++ b/src/view/name.rs
@@ -1,14 +1,17 @@
+use yew::services::ConsoleService;
+use yewtil::ptr::Irc;
+use yewtil::ptr::Mrc;
use crate::viewmodel::Error;
use crate::view::WeakComponentLink;
use yew::prelude::*;
-use vobject::Property;
+use yewtil::NeqAssign;
use crate::viewmodel::name::*;
use crate::viewmodel::VCardPropertyInputObject;
use super::VCardPropertyInputComponent;
pub struct NameView {
props: Props,
- value: Name,
+ value: Mrc<Name>,
error: Option<Error>,
}
@@ -24,14 +27,19 @@ pub enum Msg {
#[derive(Clone, PartialEq, Properties)]
pub struct Props {
- pub generated_name: Callback<Name>,
- pub generated_fn: Callback<String>,
+ pub generated: Callback<Irc<Name>>,
pub weak_link: WeakComponentLink<NameView>,
}
impl VCardPropertyInputComponent<Name> for NameView {
fn get_input_object(&self) -> Name {
- self.value.clone()
+ match self.value.clone().try_unwrap() {
+ Ok(name) => name,
+ Err(_) => {
+ ConsoleService::error("Couldn't unwrap name");
+ Name::new()
+ },
+ }
}
fn get_title(&self) -> String {
"Name".to_string()
@@ -48,31 +56,40 @@ impl Component for NameView {
props.weak_link.borrow_mut().replace(link);
Self {
props,
- value: Name::new(),
+ value: Mrc::new(Name::new()),
error: None,
}
}
fn update(&mut self, msg: <Self as yew::Component>::Message) -> bool {
match msg {
- Msg::UpdatePrefix(p) => self.value.prefix = p,
- Msg::UpdateFirstName(f) => self.value.first_name = f,
- Msg::UpdateMiddleName(m) => self.value.middle_name = m,
- Msg::UpdateLastName(l) => self.value.last_name = l,
- Msg::UpdateSuffix(s) => self.value.suffix = s,
- Generate => {
- self.props.generated_fn.emit(self.value.generate_fn());
- self.props.generated_name.emit(self.value);
+ Msg::UpdatePrefix(p) => match self.value.get_mut() {
+ Some(value) => value.prefix = p,
+ None => ConsoleService::info("Couldn't get mutable reference to name"),
+ },
+ Msg::UpdateFirstName(f) => match self.value.get_mut() {
+ Some(value) => value.first_name = f,
+ None => ConsoleService::info("Couldn't get mutable reference to name"),
+ },
+ Msg::UpdateMiddleName(m) => match self.value.get_mut() {
+ Some(value) => value.middle_name = m,
+ None => ConsoleService::info("Couldn't get mutable reference to name"),
+ },
+ Msg::UpdateLastName(l) => match self.value.get_mut() {
+ Some(value) => value.last_name = l,
+ None => ConsoleService::info("Couldn't get mutable reference to name"),
+ },
+ Msg::UpdateSuffix(s) => match self.value.get_mut() {
+ Some(value) => value.suffix = s,
+ None => ConsoleService::info("Couldn't get mutable reference to name"),
+ },
+ Msg::Generate => {
+ self.props.generated.emit(self.value.irc());
},
};
true
}
fn change(&mut self, props: <Self as yew::Component>::Properties) -> bool {
- if self.props != props {
- self.props = props;
- true
- } else {
- false
- }
+ self.props.neq_assign(props)
}
fn view(&self) -> yew::virtual_dom::VNode {
let link = self.props.weak_link.borrow().clone().unwrap();
diff --git a/src/view/telephone.rs b/src/view/telephone.rs
index 26d7806..ca58538 100644
--- a/src/view/telephone.rs
+++ b/src/view/telephone.rs
@@ -1,19 +1,22 @@
+use yew::services::ConsoleService;
+use yewtil::ptr::Irc;
+use yewtil::ptr::Mrc;
use crate::view::WeakComponentLink;
use crate::viewmodel::Error;
use yew::prelude::*;
+use yewtil::NeqAssign;
use crate::viewmodel::telephone::*;
use crate::viewmodel::VCardPropertyInputObject;
use super::VCardPropertyInputComponent;
pub struct TelephoneView {
props: Props,
- value: Telephone,
+ value: Mrc<Telephone>,
error: Option<Error>,
}
pub enum Msg {
UpdateNumber(String),
- UpdateExtension(String),
ToggleWork,
ToggleHome,
ToggleText,
@@ -29,13 +32,19 @@ pub enum Msg {
#[derive(Clone, PartialEq, Properties)]
pub struct Props {
- pub generated: Callback<Telephone>,
+ pub generated: Callback<Irc<Telephone>>,
pub weak_link: WeakComponentLink<TelephoneView>,
}
impl VCardPropertyInputComponent<Telephone> for TelephoneView {
fn get_input_object(&self) -> Telephone {
- self.value.clone()
+ match self.value.irc().try_unwrap() {
+ Ok(telephone) => telephone,
+ Err(_) => {
+ ConsoleService::error("Couldn't unwrap telephone");
+ Telephone::new()
+ },
+ }
}
fn get_title(&self) -> String {
"Telephone".to_string()
@@ -52,14 +61,13 @@ impl Component for TelephoneView {
props.weak_link.borrow_mut().replace(link);
Self {
props,
- value: Telephone::new(),
+ value: Mrc::new(Telephone::new()),
error: None,
}
}
fn update(&mut self, msg: <Self as yew::Component>::Message) -> bool {
match msg {
Msg::UpdateNumber(n) => self.value.number = n,
- Msg::UpdateExtension(e) => self.value.extension = e,
Msg::ToggleWork => self.value.work = !self.value.work,
Msg::ToggleHome => self.value.home = !self.value.home,
Msg::ToggleText => self.value.text = !self.value.text,
@@ -70,18 +78,13 @@ impl Component for TelephoneView {
Msg::TogglePager => self.value.pager = !self.value.pager,
Msg::ToggleTextPhone => self.value.text_phone = !self.value.text_phone,
Msg::Generate => {
- self.props.generated.emit(self.value);
+ self.props.generated.emit(self.value.irc());
}
};
true
}
fn change(&mut self, props: <Self as yew::Component>::Properties) -> bool {
- if self.props != props {
- self.props = props;
- true
- } else {
- false
- }
+ self.props.neq_assign(props)
}
fn view(&self) -> yew::virtual_dom::VNode {
let link = self.props.weak_link.borrow().clone().unwrap();