diff options
author | jelemux <jeremias.weber@protonmail.com> | 2021-02-17 19:43:30 +0100 |
---|---|---|
committer | jelemux <jeremias.weber@protonmail.com> | 2021-02-17 19:43:30 +0100 |
commit | d0d42c5ae00560e4464479a98df90ed063a1c773 (patch) | |
tree | 09ffff29b239768422bd3a9e147b75a3b3866a13 | |
parent | cb310a66e94db4e0c4f7d0373a670156b012412a (diff) | |
download | wasm-card-d0d42c5ae00560e4464479a98df90ed063a1c773.tar.gz wasm-card-d0d42c5ae00560e4464479a98df90ed063a1c773.tar.bz2 |
change dates to other_identification and add some stuff
-rw-r--r-- | src/model/address.rs | 2 | ||||
-rw-r--r-- | src/model/dates.rs | 69 | ||||
-rw-r--r-- | src/model/mod.rs | 65 | ||||
-rw-r--r-- | src/model/name.rs | 2 | ||||
-rw-r--r-- | src/model/organizational.rs | 2 | ||||
-rw-r--r-- | src/model/other_identification.rs | 116 | ||||
-rw-r--r-- | src/model/telephone.rs | 2 | ||||
-rw-r--r-- | src/model/vcard.rs | 8 | ||||
-rw-r--r-- | src/view/main.rs | 93 | ||||
-rw-r--r-- | src/view/property_group.rs | 8 |
10 files changed, 237 insertions, 130 deletions
diff --git a/src/model/address.rs b/src/model/address.rs index 2c42a98..2321f82 100644 --- a/src/model/address.rs +++ b/src/model/address.rs @@ -28,7 +28,7 @@ pub enum AddressMsg { Generate, } -impl VCardPropertyInputObject<AddressMsg> for Address { +impl VCardPropertyInputGroupObject<AddressMsg> for Address { fn new() -> Self { Self { post_office_box: String::new(), diff --git a/src/model/dates.rs b/src/model/dates.rs deleted file mode 100644 index 192f986..0000000 --- a/src/model/dates.rs +++ /dev/null @@ -1,69 +0,0 @@ -use super::*; - -/// Type that represents the vcard `anniversary` and `birthday` properties. -#[derive(Clone, Debug, PartialEq)] -pub struct Dates { - pub anniversary: String, - pub birthday: String, -} - -#[derive(Clone, PartialEq)] -pub enum DatesMsg { - UpdateAnniversary(String), - UpdateBirthday(String), - - Generate, -} - -impl VCardPropertyInputObject<DatesMsg> for Dates { - fn new() -> Self { - Self { - anniversary: String::new(), - birthday: String::new(), - } - } - fn get_title(&self) -> std::string::String { - "Dates".to_string() - } - fn get_input_fields( - &self, - link: &yew::html::Scope<PropertyGroupInputComponent<Self, DatesMsg>>, - ) -> std::vec::Vec<VCardPropertyInputField> { - let typ = String::from("date"); - vec![ - VCardPropertyInputField::Text { - label: "Anniversary".to_string(), - id: Some("anniversary".to_string()), - placeholder: None, - oninput: link.callback(|e: InputData| DatesMsg::UpdateAnniversary(e.value)), - value: self.anniversary.clone(), - typ: typ.clone(), - }, - VCardPropertyInputField::Text { - label: "Birthday".to_string(), - id: Some("birthday".to_string()), - placeholder: None, - oninput: link.callback(|e: InputData| DatesMsg::UpdateBirthday(e.value)), - value: self.birthday.clone(), - typ, - }, - ] - } - fn update( - &mut self, - props: InputProps<Self, DatesMsg>, - msg: <PropertyGroupInputComponent<Self, DatesMsg> as yew::Component>::Message, - ) -> bool { - match msg { - DatesMsg::UpdateAnniversary(a) => self.anniversary = a, - DatesMsg::UpdateBirthday(b) => self.birthday = b, - DatesMsg::Generate => { - props.generated.emit(self.clone()); - } - }; - true - } - fn is_empty(&self) -> bool { - self.anniversary.is_empty() && self.birthday.is_empty() - } -} diff --git a/src/model/mod.rs b/src/model/mod.rs index 45c91f1..b8dcfff 100644 --- a/src/model/mod.rs +++ b/src/model/mod.rs @@ -7,23 +7,23 @@ use yew::prelude::*; use yew::services::ConsoleService; pub mod address; -pub mod dates; pub mod name; pub mod organizational; +pub mod other_identification; 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<M: 'static + PartialEq + Clone>: Clone + PartialEq +pub trait VCardPropertyInputGroupObject<M: 'static + PartialEq + Clone>: Clone + PartialEq where Self: Sized, { - /// Function for creating a new (and empty) `VCardPropertyInputObject`. + /// Function for creating a new (and empty) `VCardPropertyInputGroupObject`. fn new() -> Self; /// Getter function for the title of the component fn get_title(&self) -> String; - /// Converts each field of the `VCardPropertyInputObject` to a VCardPropertyInputField and returns them as a vector. + /// Converts each field of the `VCardPropertyInputGroupObject` to a VCardPropertyInputField and returns them as a vector. fn get_input_fields( &self, link: &ComponentLink<PropertyGroupInputComponent<Self, M>>, @@ -33,7 +33,7 @@ where props: InputProps<Self, M>, msg: <PropertyGroupInputComponent<Self, M> as yew::Component>::Message, ) -> bool; - /// Returns a `Html` representation of the `VCardPropertyInputObject`. + /// Returns a `Html` representation of the `VCardPropertyInputGroupObject`. fn render(&self, link: &ComponentLink<PropertyGroupInputComponent<Self, M>>) -> Html { html! { <div class="columns is-mobile is-multiline"> @@ -45,7 +45,7 @@ where </div> } } - /// Convenience function for checking if the `VCardPropertyInputObject` is empty. + /// Convenience function for checking if the `VCardPropertyInputGroupObject` is empty. fn is_empty(&self) -> bool; } @@ -73,6 +73,13 @@ pub enum VCardPropertyInputField { callback: Callback<Option<File>>, value: Option<File>, }, + Select { + label: String, + id: Option<String>, + options: Vec<(String, String)>, + onchange: Callback<ChangeData>, + value: String, + }, CheckBox { label: String, id: Option<String>, @@ -99,6 +106,13 @@ impl VCardPropertyInputField { callback, value, } => Self::file_field_input(label, name, callback, value), + Self::Select { + label, + id, + options, + onchange, + value, + } => Self::select_field_input(label, id, options, onchange, value), Self::CheckBox { label, id, @@ -180,10 +194,10 @@ impl VCardPropertyInputField { }); html! { <div class="field column - is-one-fifth-widescreen - is-one-quarter-desktop - is-one-third-tablet - is-half-mobile" > + is-one-third-widescreen + is-two-quarters-desktop + is-two-thirds-tablet + is-full-mobile" > <label class="label">{ label }</label> <div class="file has-name control"> <label class="file-label"> @@ -213,6 +227,37 @@ impl VCardPropertyInputField { </div> } } + fn select_field_input( + label: &str, + id: &Option<String>, + options: &Vec<(String, String)>, + onchange: &Callback<ChangeData>, + value: &str, + ) -> Html { + html! { + <div class="field column + is-one-fifth-widescreen + is-one-quarter-desktop + is-one-third-tablet + is-half-mobile" > + <label class="label">{ label }</label> + <div class="select"> + <select id=id.as_ref().unwrap_or(&"".to_string()) + value=value + onchange=onchange > + { + for options.iter().map(|option| + html! { + <option value=option.0>{ option.1.clone() }</option> + } + ) + } + </select> + </div> + + </div> + } + } /// Returns an `Html` representation of a checkbox input field with the given parameters. fn checkbox_field_input( label: &str, diff --git a/src/model/name.rs b/src/model/name.rs index 915579d..8cc889c 100644 --- a/src/model/name.rs +++ b/src/model/name.rs @@ -35,7 +35,7 @@ pub enum NameMsg { Generate, } -impl VCardPropertyInputObject<NameMsg> for Name { +impl VCardPropertyInputGroupObject<NameMsg> for Name { fn new() -> Self { Self { prefix: String::new(), diff --git a/src/model/organizational.rs b/src/model/organizational.rs index f82f5d7..cfdb44d 100644 --- a/src/model/organizational.rs +++ b/src/model/organizational.rs @@ -22,7 +22,7 @@ pub enum OrganizationalMsg { Generate, } -impl VCardPropertyInputObject<OrganizationalMsg> for Organizational { +impl VCardPropertyInputGroupObject<OrganizationalMsg> for Organizational { fn new() -> Self { Self { org: String::new(), diff --git a/src/model/other_identification.rs b/src/model/other_identification.rs new file mode 100644 index 0000000..a01b818 --- /dev/null +++ b/src/model/other_identification.rs @@ -0,0 +1,116 @@ +use super::*; + +/// Type that represents the vcard `anniversary` and `birthday` properties. +#[derive(Clone, Debug, PartialEq)] +pub struct OtherIdentification { + pub nickname: String, + pub photo: Option<File>, + pub birthday: String, + pub anniversary: String, + pub gender: String, +} + +#[derive(Clone, PartialEq)] +pub enum OtherIdentificationMsg { + UpdateNickname(String), + UpdatePhoto(Option<File>), + UpdateBirthday(String), + UpdateAnniversary(String), + UpdateGender(String), + + Generate, + + Nope, +} + +impl VCardPropertyInputGroupObject<OtherIdentificationMsg> for OtherIdentification { + fn new() -> Self { + Self { + nickname: String::new(), + photo: None, + birthday: String::new(), + anniversary: String::new(), + gender: String::new(), + } + } + fn get_title(&self) -> std::string::String { + "Other Identification Properties".to_string() + } + fn get_input_fields( + &self, + link: &yew::html::Scope<PropertyGroupInputComponent<Self, OtherIdentificationMsg>>, + ) -> std::vec::Vec<VCardPropertyInputField> { + vec![ + VCardPropertyInputField::Text { + label: String::from("Nickname"), + id: Some(String::from("nickname")), + placeholder: None, + oninput: link + .callback(|e: InputData| OtherIdentificationMsg::UpdateNickname(e.value)), + value: self.nickname.clone(), + typ: String::from("text"), + }, + VCardPropertyInputField::File { + label: String::from("Photo"), + name: String::from("photo"), + callback: link + .callback(|file: Option<File>| OtherIdentificationMsg::UpdatePhoto(file)), + value: self.photo.clone(), + }, + VCardPropertyInputField::Text { + label: "Birthday".to_string(), + id: Some("birthday".to_string()), + placeholder: None, + oninput: link + .callback(|e: InputData| OtherIdentificationMsg::UpdateBirthday(e.value)), + value: self.birthday.clone(), + typ: String::from("date"), + }, + VCardPropertyInputField::Text { + label: "Anniversary".to_string(), + id: Some("anniversary".to_string()), + placeholder: None, + oninput: link + .callback(|e: InputData| OtherIdentificationMsg::UpdateAnniversary(e.value)), + value: self.anniversary.clone(), + typ: String::from("date"), + }, + VCardPropertyInputField::Select { + label: String::from("Gender"), + id: Some(String::from("gender")), + options: vec![ + (String::from(""), String::from("Select one")), + (String::from("M"), String::from("Male")), + (String::from("F"), String::from("Female")), + (String::from("O"), String::from("Other")), + (String::from("N"), String::from("Not applicable")), + (String::from("U"), String::from("Unknown")), + ], + onchange: link.callback(|c: ChangeData| match c { + ChangeData::Select(v) => OtherIdentificationMsg::UpdateGender(v.value()), + _ => OtherIdentificationMsg::Nope, + }), + value: self.gender.clone(), + }, + ] + } + fn update( + &mut self, + props: InputProps<Self, OtherIdentificationMsg>, + msg: <PropertyGroupInputComponent<Self, OtherIdentificationMsg> as yew::Component>::Message, + ) -> bool { + match msg { + OtherIdentificationMsg::UpdateNickname(n) => self.nickname = n, + OtherIdentificationMsg::UpdatePhoto(p) => self.photo = p, + OtherIdentificationMsg::UpdateBirthday(b) => self.birthday = b, + OtherIdentificationMsg::UpdateAnniversary(a) => self.anniversary = a, + OtherIdentificationMsg::UpdateGender(g) => self.gender = g, + OtherIdentificationMsg::Generate => props.generated.emit(self.clone()), + OtherIdentificationMsg::Nope => (), + }; + true + } + fn is_empty(&self) -> bool { + self.anniversary.is_empty() && self.birthday.is_empty() + } +} diff --git a/src/model/telephone.rs b/src/model/telephone.rs index 946da33..b571aa4 100644 --- a/src/model/telephone.rs +++ b/src/model/telephone.rs @@ -30,7 +30,7 @@ pub enum TelephoneMsg { Generate, } -impl VCardPropertyInputObject<TelephoneMsg> for Telephone { +impl VCardPropertyInputGroupObject<TelephoneMsg> for Telephone { fn new() -> Self { Self { number: String::new(), diff --git a/src/model/vcard.rs b/src/model/vcard.rs index ee7e28e..185ae71 100644 --- a/src/model/vcard.rs +++ b/src/model/vcard.rs @@ -1,7 +1,7 @@ use crate::model::address::Address; -use crate::model::dates::Dates; use crate::model::name::Name; use crate::model::organizational::Organizational; +use crate::model::other_identification::OtherIdentification; use crate::model::telephone::Telephone; /// Type that represents the data structure of a vcard. @@ -10,7 +10,7 @@ pub struct VCardData { pub names: Vec<Name>, pub addresses: Vec<Address>, pub telephones: Vec<Telephone>, - pub datess: Vec<Dates>, + pub other_identifications: Vec<OtherIdentification>, pub organizationals: Vec<Organizational>, } @@ -28,13 +28,13 @@ impl VCardData { names: Vec::new(), addresses: Vec::new(), telephones: Vec::new(), - datess: Vec::new(), + other_identifications: Vec::new(), organizationals: Vec::new(), } } make_vec_adder_fn!( fn add_name names => name: Name ); make_vec_adder_fn!( fn add_address addresses => address: Address ); 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_other_identification other_identifications => other_identification: OtherIdentification ); make_vec_adder_fn!( fn add_organizational organizationals => organizational: Organizational ); } diff --git a/src/view/main.rs b/src/view/main.rs index d35fb59..808b160 100644 --- a/src/view/main.rs +++ b/src/view/main.rs @@ -1,14 +1,14 @@ -use crate::view::property_group::PropertyGroupInputComponent; -use crate::view::weak_links::WeakComponentLink; use crate::model::address::*; -use crate::model::dates::*; use crate::model::name::*; use crate::model::organizational::*; +use crate::model::other_identification::*; use crate::model::telephone::*; use crate::model::utility::*; use crate::model::vcard::VCardData; use crate::model::Error; -use crate::model::VCardPropertyInputObject; +use crate::model::VCardPropertyInputGroupObject; +use crate::view::property_group::PropertyGroupInputComponent; +use crate::view::weak_links::WeakComponentLink; use boolinator::Boolinator; use chrono::prelude::*; use genpdf::Element as _; @@ -23,7 +23,8 @@ use yewtil::ptr::Mrc; type NameView = PropertyGroupInputComponent<Name, NameMsg>; type AddressView = PropertyGroupInputComponent<Address, AddressMsg>; -type DatesView = PropertyGroupInputComponent<Dates, DatesMsg>; +type OtherIdentificationView = + PropertyGroupInputComponent<OtherIdentification, OtherIdentificationMsg>; type OrganizationalView = PropertyGroupInputComponent<Organizational, OrganizationalMsg>; type TelephoneView = PropertyGroupInputComponent<Telephone, TelephoneMsg>; @@ -37,7 +38,7 @@ pub struct MainView { name_links: Vec<WeakComponentLink<NameView>>, address_links: Vec<WeakComponentLink<AddressView>>, telephone_links: Vec<WeakComponentLink<TelephoneView>>, - dates_links: Vec<WeakComponentLink<DatesView>>, + other_identifications_links: Vec<WeakComponentLink<OtherIdentificationView>>, organizational_links: Vec<WeakComponentLink<OrganizationalView>>, answer_count: usize, @@ -54,9 +55,9 @@ pub enum Msg { Generate, GeneratedName(Name), + GeneratedOtherIdentification(OtherIdentification), GeneratedAddress(Address), GeneratedTelephone(Telephone), - GeneratedDates(Dates), GeneratedOrganizational(Organizational), GenerationComplete, @@ -78,7 +79,7 @@ impl Component for MainView { name_links: vec![WeakComponentLink::default()], address_links: vec![WeakComponentLink::default()], telephone_links: vec![WeakComponentLink::default()], - dates_links: vec![WeakComponentLink::default()], + other_identifications_links: vec![WeakComponentLink::default()], organizational_links: vec![WeakComponentLink::default()], answer_count: 0, } @@ -102,7 +103,7 @@ impl Component for MainView { shouldrender = true; } Msg::AddDates => { - self.dates_links.push(WeakComponentLink::default()); + self.other_identifications_links.push(WeakComponentLink::default()); shouldrender = true; } Msg::AddOrganizational => { @@ -132,9 +133,9 @@ impl Component for MainView { telephone_link.send_message(TelephoneMsg::Generate); } - for dates_link in self.dates_links.iter() { + for dates_link in self.other_identifications_links.iter() { let dates_link = dates_link.borrow().clone().unwrap(); - dates_link.send_message(DatesMsg::Generate) + dates_link.send_message(OtherIdentificationMsg::Generate) } for organizational_links in self.organizational_links.iter() { @@ -172,37 +173,37 @@ impl Component for MainView { shouldrender = true; } - Msg::GeneratedAddress(address) => { + Msg::GeneratedOtherIdentification(other_identification) => { self.answer_count += 1; match self.vcard_data.get_mut() { - Some(vcard_data) => vcard_data.add_address(address), + Some(vcard_data) => vcard_data.add_other_identification(other_identification), None => ConsoleService::info( - "Error in GeneratedAddress: Couldn't get mutable borrow of VCardData", + "Error in GeneratedOtherIdentification: Couldn't get mutable borrow of VCardData", ), }; shouldrender = true; } - Msg::GeneratedTelephone(telephone) => { + Msg::GeneratedAddress(address) => { self.answer_count += 1; match self.vcard_data.get_mut() { - Some(vcard_data) => vcard_data.add_telephone(telephone), + Some(vcard_data) => vcard_data.add_address(address), None => ConsoleService::info( - "Error in GeneratedTelephone: Couldn't get mutable borrow of VCardData", + "Error in GeneratedAddress: Couldn't get mutable borrow of VCardData", ), }; shouldrender = true; } - Msg::GeneratedDates(dates) => { + Msg::GeneratedTelephone(telephone) => { self.answer_count += 1; match self.vcard_data.get_mut() { - Some(vcard_data) => vcard_data.add_dates(dates), + Some(vcard_data) => vcard_data.add_telephone(telephone), None => ConsoleService::info( - "Error in GeneratedDates: Couldn't get mutable borrow of VCardData", + "Error in GeneratedTelephone: Couldn't get mutable borrow of VCardData", ), }; @@ -336,13 +337,27 @@ impl Component for MainView { } } - for dates in vcard_data.datess { - if !dates.anniversary.is_empty() { - builder = builder.with_anniversary(dates.anniversary); + for other_identification in vcard_data.other_identifications { + if !other_identification.nickname.is_empty() { + builder = + builder.with_nickname(parameters!(), other_identification.nickname); + } + + match other_identification.photo { + Some(file) => builder = builder.with_photo(parameters!(), file.content), + None => (), + }; + + if !other_identification.anniversary.is_empty() { + builder = builder.with_anniversary(other_identification.anniversary); } - if !dates.birthday.is_empty() { - builder = builder.with_bday(parameters!(), dates.birthday); + if !other_identification.birthday.is_empty() { + builder = builder.with_bday(parameters!(), other_identification.birthday); + } + + if !other_identification.gender.is_empty() { + builder = builder.with_gender(parameters!(), other_identification.gender); } } @@ -484,6 +499,19 @@ impl Component for MainView { } { + for self.other_identifications_links.iter().map(|link| + html!{ + <OtherIdentificationView weak_link=link + generated=self.link.callback( + |d: OtherIdentification| + Msg::GeneratedOtherIdentification(d) + ) + /> + } + ) + } + + { for self.address_links.iter().map(|link| html!{ <AddressView weak_link=link @@ -510,19 +538,6 @@ impl Component for MainView { } { - for self.dates_links.iter().map(|link| - html!{ - <DatesView weak_link=link - generated=self.link.callback( - |d: Dates| - Msg::GeneratedDates(d) - ) - /> - } - ) - } - - { for self.organizational_links.iter().map(|link| html!{ <OrganizationalView weak_link=link @@ -695,7 +710,7 @@ impl MainView { self.name_links.len() + self.address_links.len() + self.telephone_links.len() - + self.dates_links.len() + + self.other_identifications_links.len() + self.organizational_links.len() } } diff --git a/src/view/property_group.rs b/src/view/property_group.rs index 9c86e80..f4b62a4 100644 --- a/src/view/property_group.rs +++ b/src/view/property_group.rs @@ -5,7 +5,7 @@ use yewtil::NeqAssign; #[derive(Clone, PartialEq, Properties)] pub struct InputProps< - O: 'static + VCardPropertyInputObject<M> + Clone, + O: 'static + VCardPropertyInputGroupObject<M> + Clone, M: 'static + PartialEq + Clone, > { pub generated: Callback<O>, @@ -14,7 +14,7 @@ pub struct InputProps< #[derive(Clone, PartialEq)] pub struct PropertyGroupInputComponent< - O: 'static + VCardPropertyInputObject<M>, + O: 'static + VCardPropertyInputGroupObject<M>, M: 'static + PartialEq + Clone, > { pub props: InputProps<O, M>, @@ -22,7 +22,7 @@ pub struct PropertyGroupInputComponent< pub error: Option<Error>, } -impl<O: 'static + VCardPropertyInputObject<M>, M: 'static + PartialEq + Clone> Component +impl<O: 'static + VCardPropertyInputGroupObject<M>, M: 'static + PartialEq + Clone> Component for PropertyGroupInputComponent<O, M> { type Message = M; @@ -57,7 +57,7 @@ impl<O: 'static + VCardPropertyInputObject<M>, M: 'static + PartialEq + Clone> C } } -impl<O: VCardPropertyInputObject<M>, M: 'static + PartialEq + Clone> +impl<O: VCardPropertyInputGroupObject<M>, M: 'static + PartialEq + Clone> PropertyGroupInputComponent<O, M> { /// Returns the error as `Html` |