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)]  | 
