summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/view/main.rs7
-rw-r--r--src/view/organizational.rs3
-rw-r--r--src/viewmodel/mod.rs95
-rw-r--r--src/viewmodel/organizational.rs47
-rw-r--r--src/viewmodel/utility.rs6
5 files changed, 145 insertions, 13 deletions
diff --git a/src/view/main.rs b/src/view/main.rs
index c2af72a..d6b2cb9 100644
--- a/src/view/main.rs
+++ b/src/view/main.rs
@@ -377,9 +377,10 @@ impl Component for MainView {
builder = builder.with_org(vec![organizational.org]);
}
- if !organizational.logo.is_empty() {
- builder = builder.with_logo(organizational.logo);
- }
+ match organizational.logo {
+ Some(file) => builder = builder.with_logo(file.content),
+ None => (),
+ };
if !organizational.title.is_empty() {
builder = builder.with_title(organizational.title);
diff --git a/src/view/organizational.rs b/src/view/organizational.rs
index b11c181..e6636ec 100644
--- a/src/view/organizational.rs
+++ b/src/view/organizational.rs
@@ -1,3 +1,4 @@
+use crate::viewmodel::utility::File;
use yew::prelude::*;
use yewtil::NeqAssign;
use crate::viewmodel::Error;
@@ -17,7 +18,7 @@ pub struct OrganizationalView {
pub enum Msg {
UpdateOrg(String),
- UpdateLogo(String),
+ UpdateLogo(Option<File>),
UpdateTitle(String),
UpdateRole(String),
UpdateMember(String),
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!{
diff --git a/src/viewmodel/organizational.rs b/src/viewmodel/organizational.rs
index e7a4ae7..c8f7164 100644
--- a/src/viewmodel/organizational.rs
+++ b/src/viewmodel/organizational.rs
@@ -4,7 +4,7 @@ use super::*;
#[derive(Clone,Debug,PartialEq)]
pub struct Organizational {
pub org: String,
- pub logo: String,
+ pub logo: Option<File>,
pub title: String,
pub role: String,
pub member: String,
@@ -15,7 +15,7 @@ impl VCardPropertyInputObject<OrganizationalView> for Organizational {
fn new() -> Self {
Self {
org: String::new(),
- logo: String::new(),
+ logo: None,
title: String::new(),
role: String::new(),
member: String::new(),
@@ -33,13 +33,44 @@ impl VCardPropertyInputObject<OrganizationalView> for Organizational {
value: self.org.clone(),
typ: typ.clone(),
},
- VCardPropertyInputField::Text{ // TODO: Add Upload for logo
+ VCardPropertyInputField::File{ // TODO: Add Upload for logo
label: "Logo".to_string(),
- id: Some("logo".to_string()),
- placeholder: None,
- oninput: link.callback(|e: InputData| Msg::UpdateLogo(e.value)),
+ name: "logo".to_string(),
+ callback: link.callback(|file: Option<File>|
+ /*
+ if let ChangeData::Files(files) = c {
+ match files.item(0) {
+ Some(file) => {
+ let filereader = match FileReaderSync::new() {
+ Ok(reader) => reader,
+ Err(_) => {
+ ConsoleService::warn("Couldn't create new filereader.");
+ return Msg::UpdateLogo(None)
+ },
+ };
+ let content = match filereader.read_as_data_url(&file) {
+ Ok(content) => content,
+ Err(_) => {
+ ConsoleService::warn("Error: Couldn't get file as data url.");
+ return Msg::UpdateLogo(None)
+ },
+ };
+ Msg::UpdateLogo(
+ Some(File {
+ name: file.name(),
+ content,
+ })
+ )
+ },
+ None => Msg::UpdateLogo(None),
+ }
+ } else {
+ Msg::UpdateLogo(None)
+ }
+ */
+ Msg::UpdateLogo(file)
+ ),
value: self.logo.clone(),
- typ: typ.clone(),
},
VCardPropertyInputField::Text{
label: "Title".to_string(),
@@ -77,7 +108,7 @@ impl VCardPropertyInputObject<OrganizationalView> for Organizational {
}
fn is_empty(&self) -> bool {
self.org.is_empty() &&
- self.logo.is_empty() &&
+ self.logo.is_none() &&
self.title.is_empty() &&
self.role.is_empty() &&
self.member.is_empty() &&
diff --git a/src/viewmodel/utility.rs b/src/viewmodel/utility.rs
index 4a82a42..cb581ac 100644
--- a/src/viewmodel/utility.rs
+++ b/src/viewmodel/utility.rs
@@ -38,4 +38,10 @@ pub enum DownloadOption {
PDF,
VCard,
QrCode,
+}
+
+#[derive(Clone,Debug,PartialEq)]
+pub struct File {
+ pub name: String,
+ pub content: String,
} \ No newline at end of file