summaryrefslogtreecommitdiff
path: root/src/model
diff options
context:
space:
mode:
Diffstat (limited to 'src/model')
-rw-r--r--src/model/input_fields.rs233
-rw-r--r--src/model/mod.rs239
-rw-r--r--src/model/property_groups/address.rs (renamed from src/model/address.rs)3
-rw-r--r--src/model/property_groups/mod.rs5
-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.rs10
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)]