diff options
Diffstat (limited to 'src/viewmodel/mod.rs')
-rw-r--r-- | src/viewmodel/mod.rs | 95 |
1 files changed, 94 insertions, 1 deletions
diff --git a/src/viewmodel/mod.rs b/src/viewmodel/mod.rs index 75ed1d2..044dbad 100644 --- a/src/viewmodel/mod.rs +++ b/src/viewmodel/mod.rs @@ -1,3 +1,8 @@ +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; @@ -50,7 +55,13 @@ pub enum VCardPropertyInputField { placeholder: Option<String>, oninput: Callback<InputData>, value: String, - typ: String + typ: String, + }, + File { + label: String, + name: String, + callback: Callback<Option<File>>, + value: Option<File>, }, CheckBox { label: String, @@ -72,6 +83,12 @@ impl VCardPropertyInputField { 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, @@ -99,6 +116,82 @@ impl VCardPropertyInputField { </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!{ |