diff options
author | jelemux <jeremias.weber@protonmail.com> | 2021-02-11 12:07:22 +0100 |
---|---|---|
committer | jelemux <jeremias.weber@protonmail.com> | 2021-02-11 12:07:22 +0100 |
commit | 0660151a8b641fa0a23dde2598132029970f7ae4 (patch) | |
tree | 0bdeb1108419add4570f278795f0bfd0f5366856 /src/viewmodel | |
parent | 036a567bae8346eb38f9237f59645dbcc4f1cd8c (diff) | |
download | wasm-card-0660151a8b641fa0a23dde2598132029970f7ae4.tar.gz wasm-card-0660151a8b641fa0a23dde2598132029970f7ae4.tar.bz2 |
refactoring - reduced code size by about a third
Diffstat (limited to 'src/viewmodel')
-rw-r--r-- | src/viewmodel/address.rs | 113 | ||||
-rw-r--r-- | src/viewmodel/dates.rs | 45 | ||||
-rw-r--r-- | src/viewmodel/mod.rs | 231 | ||||
-rw-r--r-- | src/viewmodel/name.rs | 119 | ||||
-rw-r--r-- | src/viewmodel/organizational.rs | 88 | ||||
-rw-r--r-- | src/viewmodel/telephone.rs | 106 | ||||
-rw-r--r-- | src/viewmodel/utility.rs | 45 | ||||
-rw-r--r-- | src/viewmodel/vcard.rs | 40 |
8 files changed, 0 insertions, 787 deletions
diff --git a/src/viewmodel/address.rs b/src/viewmodel/address.rs deleted file mode 100644 index 9542675..0000000 --- a/src/viewmodel/address.rs +++ /dev/null @@ -1,113 +0,0 @@ -use super::*; -use crate::view::address::*; - -#[derive(Clone, Debug, PartialEq)] -pub struct Address { - pub post_office_box: String, - pub extension: String, - pub street: String, - pub locality: String, - pub region: String, - pub code: String, - pub country: String, - pub work: bool, - pub home: bool, -} - -impl VCardPropertyInputObject<AddressView> for Address { - fn new() -> Self { - Self { - post_office_box: String::new(), - extension: String::new(), - street: String::new(), - locality: String::new(), - region: String::new(), - code: String::new(), - country: String::new(), - work: false, - home: false, - } - } - fn get_input_fields(&self, link: &ComponentLink<AddressView>) -> Vec<VCardPropertyInputField> { - let typ = String::from("text"); - vec![ - 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(), - }, - VCardPropertyInputField::Text { - label: "Extension".to_string(), - id: Some("extension".to_string()), - placeholder: None, - oninput: link.callback(|e: InputData| Msg::UpdateExtension(e.value)), - value: self.extension.clone(), - typ: typ.clone(), - }, - VCardPropertyInputField::Text { - label: "Street".to_string(), - id: Some("street".to_string()), - placeholder: None, - oninput: link.callback(|e: InputData| Msg::UpdateStreet(e.value)), - value: self.street.clone(), - typ: typ.clone(), - }, - VCardPropertyInputField::Text { - label: "Locality".to_string(), - id: Some("locality".to_string()), - placeholder: None, - oninput: link.callback(|e: InputData| Msg::UpdateLocality(e.value)), - value: self.locality.clone(), - typ: typ.clone(), - }, - VCardPropertyInputField::Text { - label: "Region".to_string(), - id: Some("region".to_string()), - placeholder: None, - oninput: link.callback(|e: InputData| Msg::UpdateRegion(e.value)), - value: self.region.clone(), - typ: typ.clone(), - }, - VCardPropertyInputField::Text { - label: "Code".to_string(), - id: Some("code".to_string()), - placeholder: None, - oninput: link.callback(|e: InputData| Msg::UpdateCode(e.value)), - value: self.code.clone(), - typ: typ.clone(), - }, - VCardPropertyInputField::Text { - label: "Country".to_string(), - id: Some("country".to_string()), - placeholder: None, - oninput: link.callback(|e: InputData| Msg::UpdateCountry(e.value)), - value: self.country.clone(), - typ, - }, - VCardPropertyInputField::CheckBox { - label: "Work".to_string(), - id: Some("work".to_string()), - onclick: link.callback(|_: MouseEvent| Msg::ToggleWork), - value: self.work, - }, - VCardPropertyInputField::CheckBox { - label: "Home".to_string(), - id: Some("home".to_string()), - onclick: link.callback(|_: MouseEvent| Msg::ToggleHome), - value: self.home, - }, - ] - } - 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() - } -} diff --git a/src/viewmodel/dates.rs b/src/viewmodel/dates.rs deleted file mode 100644 index 7d8d394..0000000 --- a/src/viewmodel/dates.rs +++ /dev/null @@ -1,45 +0,0 @@ -use super::*; -use crate::view::dates::*; - -/// Type that represents the vcard `anniversary` and `birthday` properties. -#[derive(Clone, Debug, PartialEq)] -pub struct Dates { - pub anniversary: String, - pub birthday: String, -} - -impl VCardPropertyInputObject<DatesView> for Dates { - fn new() -> Self { - Self { - anniversary: String::new(), - birthday: String::new(), - } - } - fn get_input_fields( - &self, - link: &yew::html::Scope<DatesView>, - ) -> 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| Msg::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| Msg::UpdateBirthday(e.value)), - value: self.birthday.clone(), - typ, - }, - ] - } - fn is_empty(&self) -> bool { - self.anniversary.is_empty() && self.birthday.is_empty() - } -} diff --git a/src/viewmodel/mod.rs b/src/viewmodel/mod.rs deleted file mode 100644 index 0385c61..0000000 --- a/src/viewmodel/mod.rs +++ /dev/null @@ -1,231 +0,0 @@ -use crate::view::VCardPropertyInputComponent; -use crate::viewmodel::utility::File; -use wasm_bindgen::closure::Closure; -use wasm_bindgen::JsCast; -use web_sys::FileReader; -use yew::prelude::*; -use yew::services::ConsoleService; - -pub mod address; -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, -{ - /// Function for creating a new (and empty) `VCardPropertyInputObject`. - fn new() -> Self; - /// Converts each field of the `VCardPropertyInputObject` to a VCardPropertyInputField and returns them as a vector. - 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! { - <div class="columns is-mobile is-multiline"> - { - for self.get_input_fields(link).iter().map(|field| - field.render() - ) - } - </div> - } - } - /// Convenience function for checking if the `VCardPropertyInputObject` is empty. - fn is_empty(&self) -> bool; -} - -/// Type for saving error messages. -/// -/// More of a placeholder for something better later on. -#[derive(Debug, Clone, PartialEq)] -pub struct Error { - pub msg: String, -} - -/// Type that represents the visiual appearance of an input field. -pub enum VCardPropertyInputField { - Text { - label: String, - id: Option<String>, - placeholder: Option<String>, - oninput: Callback<InputData>, - value: String, - typ: String, - }, - File { - label: String, - name: String, - callback: Callback<Option<File>>, - value: Option<File>, - }, - CheckBox { - label: String, - id: Option<String>, - onclick: Callback<MouseEvent>, - value: bool, - }, -} - -impl VCardPropertyInputField { - /// Returns a `Html` representation of the `VCardPropertyInputField`. - pub fn render(&self) -> Html { - match self { - Self::Text { - label, - id, - placeholder, - oninput, - value: _, - typ, - } => Self::text_field_input(label, id, placeholder, oninput, typ), - Self::File { - label, - name, - callback, - value, - } => Self::file_field_input(label, name, callback, value), - Self::CheckBox { - label, - id, - onclick, - value, - } => 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 - is-one-fifth-widescreen - is-one-quarter-desktop - is-one-third-tablet - is-half-mobile" > - <label class="label">{ label }</label> - <div class="control"> - <input id=id.as_ref().unwrap_or(&"".to_string()) - type=typ - placeholder=placeholder.as_ref().unwrap_or(&"".to_string()) - oninput=oninput - /> - </div> - </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 { - let callback = callback.clone(); - let onchange = Callback::<()>::default(); - let onchange = onchange.reform(move |c: ChangeData| { - if let ChangeData::Files(files) = c { - match files.item(0) { - Some(file) => { - let file_reader = FileReader::new().unwrap(); - match file_reader.read_as_data_url(&file) { - Ok(_) => (), - Err(_) => ConsoleService::warn("Error: Couldn't get file as data url."), - }; - - 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(); - match data_url { - 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! { - <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="file has-name control"> - <label class="file-label"> - <input class="file-input" - type="file" - name=name - onchange=onchange - /> - <span class="file-cta"> - <span class="file-icon"> - <i class="fas fa-upload"></i> - </span> - <span class="file-label"> - { "Choose file..." } - </span> - </span> - <span class="file-name"> - { - match file { - Some(file) => file.name.clone(), - None => String::from("No file selected"), - } - } - </span> - </label> - </div> - </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 - 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" - checked=*checked - onclick=onclick - /> - { label } - </label> - </div> - } - } -} diff --git a/src/viewmodel/name.rs b/src/viewmodel/name.rs deleted file mode 100644 index de0aa81..0000000 --- a/src/viewmodel/name.rs +++ /dev/null @@ -1,119 +0,0 @@ -use super::*; -use crate::view::name::*; - -/// Type that represents a vcard `name` property -/// -/// # Examples -/// ``` -/// # use bcard_wasm_webapp::viewmodel::name::Name; -/// # use crate::bcard_wasm_webapp::viewmodel::VCardPropertyInputObject; -/// let mut name = Name::new(); -/// name.prefix = String::from("Sir"); -/// name.first_name = String::from("Arthur"); -/// 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)] -pub struct Name { - pub prefix: String, - pub first_name: String, - pub middle_name: String, - pub last_name: String, - pub suffix: String, -} - -impl VCardPropertyInputObject<NameView> for Name { - fn new() -> Self { - Self { - prefix: String::new(), - first_name: String::new(), - middle_name: String::new(), - last_name: String::new(), - suffix: String::new(), - } - } - fn get_input_fields( - &self, - link: &ComponentLink<NameView>, - ) -> std::vec::Vec<VCardPropertyInputField> { - let typ = String::from("text"); - vec![ - VCardPropertyInputField::Text { - label: "Prefix".to_string(), - id: Some("prefix".to_string()), - placeholder: Some("Sir".to_string()), - oninput: link.callback(|e: InputData| Msg::UpdatePrefix(e.value)), - value: self.prefix.clone(), - typ: typ.clone(), - }, - VCardPropertyInputField::Text { - label: "First Name".to_string(), - id: Some("first_name".to_string()), - placeholder: Some("Arthur".to_string()), - oninput: link.callback(|e: InputData| Msg::UpdateFirstName(e.value)), - value: self.first_name.clone(), - typ: typ.clone(), - }, - VCardPropertyInputField::Text { - label: "Middle Name".to_string(), - id: Some("middle_name".to_string()), - placeholder: Some("Charles".to_string()), - oninput: link.callback(|e: InputData| Msg::UpdateMiddleName(e.value)), - value: self.middle_name.clone(), - typ: typ.clone(), - }, - VCardPropertyInputField::Text { - label: "Last Name".to_string(), - id: Some("last_name".to_string()), - placeholder: Some("Clarke".to_string()), - oninput: link.callback(|e: InputData| Msg::UpdateLastName(e.value)), - value: self.last_name.clone(), - typ: typ.clone(), - }, - VCardPropertyInputField::Text { - label: "Suffix".to_string(), - id: Some("suffix".to_string()), - placeholder: Some("CBE FRAS".to_string()), - oninput: link.callback(|e: InputData| Msg::UpdateSuffix(e.value)), - value: self.suffix.clone(), - typ, - }, - ] - } - 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() - } -} - -impl Name { - pub fn generate_fn(&self) -> String { - let mut full_name = String::new(); - - full_name.push_str(&self.prefix); - if !self.first_name.is_empty() { - full_name.push_str(" "); - full_name.push_str(&self.first_name); - } - if !self.middle_name.is_empty() { - full_name.push_str(" "); - full_name.push_str(&self.middle_name); - } - if !self.last_name.is_empty() { - full_name.push_str(" "); - full_name.push_str(&self.last_name); - } - if !self.suffix.is_empty() { - full_name.push_str(", "); - full_name.push_str(&self.suffix); - } - - full_name - } -} diff --git a/src/viewmodel/organizational.rs b/src/viewmodel/organizational.rs deleted file mode 100644 index 72b19d2..0000000 --- a/src/viewmodel/organizational.rs +++ /dev/null @@ -1,88 +0,0 @@ -use super::*; -use crate::view::organizational::*; - -#[derive(Clone, Debug, PartialEq)] -pub struct Organizational { - pub org: String, - pub logo: Option<File>, - pub title: String, - pub role: String, - pub member: String, - pub related: String, -} - -impl VCardPropertyInputObject<OrganizationalView> for Organizational { - fn new() -> Self { - Self { - org: String::new(), - logo: None, - title: String::new(), - role: String::new(), - member: String::new(), - related: String::new(), - } - } - fn get_input_fields( - &self, - link: &yew::html::Scope<OrganizationalView>, - ) -> std::vec::Vec<VCardPropertyInputField> { - let typ = String::from("text"); - vec![ - VCardPropertyInputField::Text { - label: "Organisation".to_string(), - id: Some("org".to_string()), - placeholder: None, - oninput: link.callback(|e: InputData| Msg::UpdateOrg(e.value)), - value: self.org.clone(), - typ: typ.clone(), - }, - VCardPropertyInputField::File { - // TODO: Add Upload for logo - label: "Logo".to_string(), - name: "logo".to_string(), - callback: link.callback(|file: Option<File>| Msg::UpdateLogo(file)), - value: self.logo.clone(), - }, - VCardPropertyInputField::Text { - label: "Title".to_string(), - id: Some("title".to_string()), - placeholder: None, - oninput: link.callback(|e: InputData| Msg::UpdateTitle(e.value)), - value: self.title.clone(), - typ: typ.clone(), - }, - VCardPropertyInputField::Text { - label: "Role".to_string(), - id: Some("role".to_string()), - placeholder: None, - oninput: link.callback(|e: InputData| Msg::UpdateRole(e.value)), - value: self.role.clone(), - typ: typ.clone(), - }, - VCardPropertyInputField::Text { - label: "Member".to_string(), - id: Some("member".to_string()), - placeholder: None, - oninput: link.callback(|e: InputData| Msg::UpdateMember(e.value)), - value: self.member.clone(), - typ: typ.clone(), - }, - VCardPropertyInputField::Text { - label: "Related".to_string(), - id: Some("related".to_string()), - placeholder: None, - oninput: link.callback(|e: InputData| Msg::UpdateRelated(e.value)), - value: self.related.clone(), - typ: typ, - }, - ] - } - 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() - } -} diff --git a/src/viewmodel/telephone.rs b/src/viewmodel/telephone.rs deleted file mode 100644 index 44b938f..0000000 --- a/src/viewmodel/telephone.rs +++ /dev/null @@ -1,106 +0,0 @@ -use super::*; -use crate::view::telephone::*; - -#[derive(Clone, Debug, PartialEq)] -pub struct Telephone { - pub number: String, - pub work: bool, - pub home: bool, - pub text: bool, - pub voice: bool, - pub fax: bool, - pub cell: bool, - pub video: bool, - pub pager: bool, - pub text_phone: bool, -} - -impl VCardPropertyInputObject<TelephoneView> for Telephone { - fn new() -> Self { - Self { - number: String::new(), - work: false, - home: false, - text: false, - voice: false, - fax: false, - cell: false, - video: false, - pager: false, - text_phone: false, - } - } - fn get_input_fields( - &self, - link: &ComponentLink<TelephoneView>, - ) -> Vec<VCardPropertyInputField> { - let typ = String::from("tel"); - vec![ - VCardPropertyInputField::Text { - label: "Number".to_string(), - id: Some("number".to_string()), - placeholder: None, - oninput: link.callback(|e: InputData| Msg::UpdateNumber(e.value)), - value: self.number.clone(), - typ, - }, - VCardPropertyInputField::CheckBox { - label: "Work".to_string(), - id: Some("work".to_string()), - onclick: link.callback(|_: MouseEvent| Msg::ToggleWork), - value: self.work, - }, - VCardPropertyInputField::CheckBox { - label: "Home".to_string(), - id: Some("home".to_string()), - onclick: link.callback(|_: MouseEvent| Msg::ToggleHome), - value: self.home, - }, - VCardPropertyInputField::CheckBox { - label: "Text".to_string(), - id: Some("text".to_string()), - onclick: link.callback(|_: MouseEvent| Msg::ToggleText), - value: self.text, - }, - VCardPropertyInputField::CheckBox { - label: "Voice".to_string(), - id: Some("voice".to_string()), - onclick: link.callback(|_: MouseEvent| Msg::ToggleVoice), - value: self.voice, - }, - VCardPropertyInputField::CheckBox { - label: "Fax".to_string(), - id: Some("fax".to_string()), - onclick: link.callback(|_: MouseEvent| Msg::ToggleFax), - value: self.fax, - }, - VCardPropertyInputField::CheckBox { - label: "Cell".to_string(), - id: Some("cell".to_string()), - onclick: link.callback(|_: MouseEvent| Msg::ToggleCell), - value: self.cell, - }, - VCardPropertyInputField::CheckBox { - label: "Video".to_string(), - id: Some("video".to_string()), - onclick: link.callback(|_: MouseEvent| Msg::ToggleVideo), - value: self.video, - }, - VCardPropertyInputField::CheckBox { - label: "Pager".to_string(), - id: Some("pager".to_string()), - onclick: link.callback(|_: MouseEvent| Msg::TogglePager), - value: self.pager, - }, - VCardPropertyInputField::CheckBox { - label: "Text Phone".to_string(), - id: Some("text_phone".to_string()), - onclick: link.callback(|_: MouseEvent| Msg::ToggleTextPhone), - value: self.text_phone, - }, - ] - } - fn is_empty(&self) -> bool { - self.number.is_empty() - } -} diff --git a/src/viewmodel/utility.rs b/src/viewmodel/utility.rs deleted file mode 100644 index 617ee45..0000000 --- a/src/viewmodel/utility.rs +++ /dev/null @@ -1,45 +0,0 @@ -#[derive(Clone)] -pub struct Download { - pub file_name: String, - pub content: String, - pub mime_type: MimeType, -} - -impl Download { - pub fn as_data_link(&self) -> String { - let data = base64::encode(&*self.content); - let uri_component: String = js_sys::encode_uri_component(&data).into(); - - format!("data:{};base64,{}", self.mime_type.as_text(), uri_component) - } -} - -#[derive(Clone, Copy)] -pub enum MimeType { - PDF, - VCard, - SVG, -} - -impl MimeType { - pub fn as_text(&self) -> &str { - match self { - MimeType::PDF => "application/pdf", - MimeType::VCard => "text/vcard", - MimeType::SVG => "image/svg+xml", - } - } -} - -#[derive(Clone, Copy, PartialEq)] -pub enum DownloadOption { - PDF, - VCard, - QrCode, -} - -#[derive(Clone, Debug, PartialEq)] -pub struct File { - pub name: String, - pub content: String, -} diff --git a/src/viewmodel/vcard.rs b/src/viewmodel/vcard.rs deleted file mode 100644 index 18ce43a..0000000 --- a/src/viewmodel/vcard.rs +++ /dev/null @@ -1,40 +0,0 @@ -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)] -pub struct VCardData { - pub names: Vec<Name>, - pub addresses: Vec<Address>, - pub telephones: Vec<Telephone>, - pub datess: Vec<Dates>, - pub organizationals: Vec<Organizational>, -} - -macro_rules! make_vec_adder_fn { - ( fn $fnname:ident $property:ident => $($arg_name:ident : $arg_type:ty),* ) => { - pub fn $fnname(&mut self, $( $arg_name : $arg_type ),*) { - $(self.$property.push($arg_name);)* - } - }; -} - -impl VCardData { - pub fn new() -> Self { - Self { - names: Vec::new(), - addresses: Vec::new(), - telephones: Vec::new(), - datess: 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_organizational organizationals => organizational: Organizational ); -} |