use wasm_bindgen::closure::Closure; use web_sys::FileReader; use wasm_bindgen::JsCast; use yew::services::ConsoleService; use crate::viewmodel::utility::File; use yew::prelude::*; use crate::view::VCardPropertyInputComponent; pub mod vcard; pub mod utility; pub mod address; pub mod name; pub mod telephone; pub mod dates; pub mod organizational; /// Trait for types that represent the data of a vcard property used inside of a `VCardPropertyInputComponent`. pub trait VCardPropertyInputObject>: 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) -> Vec; /// Returns a `Html` representation of the `VCardPropertyInputObject`. fn render(&self, link: &ComponentLink) -> Html { html!{
{ for self.get_input_fields(link).iter().map(|field| field.render() ) }
} } /// 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, placeholder: Option, oninput: Callback, value: String, typ: String, }, File { label: String, name: String, callback: Callback>, value: Option, }, CheckBox { label: String, id: Option, onclick: Callback, 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, placeholder: &Option, oninput: &Callback, typ: &str) -> Html { html!{
} } /// Returns an `Html` representation of a file input field with the given parameters. fn file_field_input(label: &str, name: &str, callback: &Callback>, file: &Option) -> 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 = 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); file_reader.set_onload(Some(onload.as_ref().unchecked_ref())); onload.forget(); }, None => callback.emit(None), } } else { callback.emit(None); } ); html!{
} } /// Returns an `Html` representation of a checkbox input field with the given parameters. fn checkbox_field_input(label: &str, id: &Option, checked: &bool, onclick: &Callback) -> Html { html!{
} } }