diff options
Diffstat (limited to 'src/model')
-rw-r--r-- | src/model/input_fields.rs | 233 | ||||
-rw-r--r-- | src/model/mod.rs | 239 | ||||
-rw-r--r-- | src/model/property_groups/address.rs (renamed from src/model/address.rs) | 3 | ||||
-rw-r--r-- | src/model/property_groups/mod.rs | 5 | ||||
-rw-r--r-- | src/model/property_groups/name.rs (renamed from src/model/name.rs) | 3 | ||||
-rw-r--r-- | src/model/property_groups/organizational.rs (renamed from src/model/organizational.rs) | 3 | ||||
-rw-r--r-- | src/model/property_groups/other_identification.rs (renamed from src/model/other_identification.rs) | 3 | ||||
-rw-r--r-- | src/model/property_groups/telephone.rs (renamed from src/model/telephone.rs) | 3 | ||||
-rw-r--r-- | src/model/vcard.rs | 10 |
9 files changed, 256 insertions, 246 deletions
diff --git a/src/model/input_fields.rs b/src/model/input_fields.rs new file mode 100644 index 0000000..91d9264 --- /dev/null +++ b/src/model/input_fields.rs @@ -0,0 +1,233 @@ +use crate::model::utility::File; +use wasm_bindgen::closure::Closure; +use wasm_bindgen::JsCast; +use web_sys::FileReader; +use yew::prelude::*; +use yew::services::ConsoleService; + +/// 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>, + }, + Select { + label: String, + id: Option<String>, + options: Vec<(String, String)>, + onchange: Callback<ChangeData>, + value: String, + }, + 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::Select { + label, + id, + options, + onchange, + value, + } => Self::select_field_input(label, id, options, onchange, 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-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"> + <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> + } + } + 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, + 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/model/mod.rs b/src/model/mod.rs index b8dcfff..4e3ad87 100644 --- a/src/model/mod.rs +++ b/src/model/mod.rs @@ -1,16 +1,10 @@ use crate::model::utility::File; use crate::view::property_group::*; -use wasm_bindgen::closure::Closure; -use wasm_bindgen::JsCast; -use web_sys::FileReader; +use input_fields::VCardPropertyInputField; use yew::prelude::*; -use yew::services::ConsoleService; -pub mod address; -pub mod name; -pub mod organizational; -pub mod other_identification; -pub mod telephone; +pub mod input_fields; +pub mod property_groups; pub mod utility; pub mod vcard; @@ -56,230 +50,3 @@ where 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>, - }, - Select { - label: String, - id: Option<String>, - options: Vec<(String, String)>, - onchange: Callback<ChangeData>, - value: String, - }, - 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::Select { - label, - id, - options, - onchange, - value, - } => Self::select_field_input(label, id, options, onchange, 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-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"> - <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> - } - } - 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, - 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/model/address.rs b/src/model/property_groups/address.rs index 2321f82..00bca0b 100644 --- a/src/model/address.rs +++ b/src/model/property_groups/address.rs @@ -1,4 +1,5 @@ -use super::*; +use crate::model::input_fields::VCardPropertyInputField; +use crate::model::*; #[derive(Clone, Debug, PartialEq)] pub struct Address { diff --git a/src/model/property_groups/mod.rs b/src/model/property_groups/mod.rs new file mode 100644 index 0000000..3bfc9f3 --- /dev/null +++ b/src/model/property_groups/mod.rs @@ -0,0 +1,5 @@ +pub mod address; +pub mod name; +pub mod organizational; +pub mod other_identification; +pub mod telephone; diff --git a/src/model/name.rs b/src/model/property_groups/name.rs index 8cc889c..eb0d9da 100644 --- a/src/model/name.rs +++ b/src/model/property_groups/name.rs @@ -1,4 +1,5 @@ -use super::*; +use crate::model::input_fields::VCardPropertyInputField; +use crate::model::*; /// Type that represents a vcard `name` property /// diff --git a/src/model/organizational.rs b/src/model/property_groups/organizational.rs index cfdb44d..1d6ccf2 100644 --- a/src/model/organizational.rs +++ b/src/model/property_groups/organizational.rs @@ -1,4 +1,5 @@ -use super::*; +use crate::model::input_fields::VCardPropertyInputField; +use crate::model::*; #[derive(Clone, Debug, PartialEq)] pub struct Organizational { diff --git a/src/model/other_identification.rs b/src/model/property_groups/other_identification.rs index a01b818..ca48375 100644 --- a/src/model/other_identification.rs +++ b/src/model/property_groups/other_identification.rs @@ -1,4 +1,5 @@ -use super::*; +use crate::model::input_fields::VCardPropertyInputField; +use crate::model::*; /// Type that represents the vcard `anniversary` and `birthday` properties. #[derive(Clone, Debug, PartialEq)] diff --git a/src/model/telephone.rs b/src/model/property_groups/telephone.rs index b571aa4..03de4ee 100644 --- a/src/model/telephone.rs +++ b/src/model/property_groups/telephone.rs @@ -1,4 +1,5 @@ -use super::*; +use crate::model::input_fields::VCardPropertyInputField; +use crate::model::*; #[derive(Clone, Debug, PartialEq)] pub struct Telephone { diff --git a/src/model/vcard.rs b/src/model/vcard.rs index 185ae71..24a47ff 100644 --- a/src/model/vcard.rs +++ b/src/model/vcard.rs @@ -1,8 +1,8 @@ -use crate::model::address::Address; -use crate::model::name::Name; -use crate::model::organizational::Organizational; -use crate::model::other_identification::OtherIdentification; -use crate::model::telephone::Telephone; +use crate::model::property_groups::address::Address; +use crate::model::property_groups::name::Name; +use crate::model::property_groups::organizational::Organizational; +use crate::model::property_groups::other_identification::OtherIdentification; +use crate::model::property_groups::telephone::Telephone; /// Type that represents the data structure of a vcard. #[derive(Clone, Debug)] |