2022-04-06 04:39:12 +00:00
|
|
|
use js_sys::{Function, JsString, Promise};
|
|
|
|
use std::collections::HashMap;
|
|
|
|
use wasm_bindgen::{JsCast, JsValue};
|
|
|
|
use wasm_bindgen_futures::JsFuture;
|
2022-04-04 09:25:17 +00:00
|
|
|
use web_sys::{window, Document, Request, RequestInit, Window};
|
2022-03-09 08:29:53 +00:00
|
|
|
|
2022-04-06 04:39:12 +00:00
|
|
|
use crate::constants::BACKEND_URL;
|
|
|
|
|
2022-03-09 08:29:53 +00:00
|
|
|
pub fn get_window_document() -> Result<(Window, Document), String> {
|
|
|
|
let window = window().ok_or_else(|| String::from("Failed to get window"))?;
|
|
|
|
let document = window
|
|
|
|
.document()
|
|
|
|
.ok_or_else(|| String::from("Failed to get document"))?;
|
|
|
|
|
|
|
|
Ok((window, document))
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn append_to_info_text(
|
|
|
|
document: &Document,
|
|
|
|
id: &str,
|
|
|
|
msg: &str,
|
|
|
|
limit: u32,
|
|
|
|
) -> Result<(), String> {
|
|
|
|
let info_text = document
|
|
|
|
.get_element_by_id(id)
|
|
|
|
.ok_or_else(|| format!("Failed to get info_text \"{}\"", id))?;
|
|
|
|
|
|
|
|
let height = info_text.client_height();
|
|
|
|
|
|
|
|
// create the new text to be appended in the text
|
|
|
|
let p = document
|
|
|
|
.create_element("p")
|
|
|
|
.map_err(|e| format!("{:?}", e))?;
|
|
|
|
|
|
|
|
p.set_inner_html(msg);
|
|
|
|
|
|
|
|
// check if scrolled to top
|
|
|
|
let at_top: bool = info_text.scroll_top() <= height - info_text.scroll_height();
|
|
|
|
|
|
|
|
// append text to output
|
|
|
|
info_text
|
|
|
|
.append_with_node_1(&p)
|
|
|
|
.map_err(|e| format!("{:?}", e))?;
|
|
|
|
|
|
|
|
while info_text.child_element_count() > limit {
|
|
|
|
info_text
|
|
|
|
.remove_child(
|
|
|
|
&info_text.first_child().ok_or_else(|| {
|
|
|
|
format!("Failed to get first_child() of info_text \"{}\"", id)
|
|
|
|
})?,
|
|
|
|
)
|
|
|
|
.map_err(|e| format!("{:?}", e))?;
|
|
|
|
}
|
|
|
|
|
|
|
|
if at_top {
|
|
|
|
info_text.set_scroll_top(height - info_text.scroll_height());
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
2022-03-09 09:10:13 +00:00
|
|
|
|
|
|
|
pub fn element_append_class(document: &Document, id: &str, class: &str) -> Result<(), String> {
|
|
|
|
let element = document
|
|
|
|
.get_element_by_id(id)
|
|
|
|
.ok_or_else(|| format!("Failed to get element with id \"{}\"", id))?;
|
|
|
|
let new_class = format!("{} {}", element.class_name(), class);
|
|
|
|
element.set_class_name(&new_class);
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
2022-03-10 06:43:03 +00:00
|
|
|
|
|
|
|
pub fn element_remove_class(document: &Document, id: &str, class: &str) -> Result<(), String> {
|
|
|
|
let element = document
|
|
|
|
.get_element_by_id(id)
|
|
|
|
.ok_or_else(|| format!("Failed to get element with id \"{}\"", id))?;
|
|
|
|
let mut element_class: String = element.class_name();
|
|
|
|
let idx_opt = element_class.find(class);
|
|
|
|
if let Some(idx) = idx_opt {
|
|
|
|
let mut remaining = element_class.split_off(idx);
|
|
|
|
element_class += &remaining.split_off(class.len());
|
|
|
|
}
|
|
|
|
element.set_class_name(&element_class);
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
2022-04-04 09:25:17 +00:00
|
|
|
|
2022-04-06 09:43:17 +00:00
|
|
|
pub fn element_has_class(document: &Document, id: &str, class: &str) -> Result<bool, String> {
|
|
|
|
let element = document
|
|
|
|
.get_element_by_id(id)
|
|
|
|
.ok_or_else(|| format!("Failed to get element with id \"{}\"", id))?;
|
|
|
|
let element_class: String = element.class_name();
|
|
|
|
|
|
|
|
Ok(element_class.contains(class))
|
|
|
|
}
|
|
|
|
|
2022-04-04 09:25:17 +00:00
|
|
|
pub fn create_json_request(target_url: &str, json_body: &str) -> Result<Request, String> {
|
|
|
|
let mut req_init: RequestInit = RequestInit::new();
|
|
|
|
req_init.body(Some(&JsValue::from_str(json_body)));
|
2022-04-05 09:16:04 +00:00
|
|
|
req_init.method("POST");
|
|
|
|
// TODO omit the NoCors when hosted on website
|
|
|
|
req_init.mode(web_sys::RequestMode::NoCors);
|
|
|
|
// req_init.headers(
|
|
|
|
// &JsValue::from_str("{'Content-Type': 'application/json'}"),
|
|
|
|
// &JsValue::from_serde("{'Content-Type': 'application/json'}")
|
|
|
|
// .map_err(|e| format!("{}", e))?,
|
|
|
|
// &JsValue::from_serde("'headers': { 'Content-Type': 'application/json' }")
|
|
|
|
// .map_err(|e| format!("{}", e))?,
|
|
|
|
// );
|
|
|
|
|
|
|
|
let request: Request =
|
|
|
|
Request::new_with_str_and_init(target_url, &req_init).map_err(|e| format!("{:?}", e))?;
|
|
|
|
request
|
|
|
|
.headers()
|
|
|
|
.set("Content-Type", "application/json")
|
|
|
|
.map_err(|e| format!("{:?}", e))?;
|
|
|
|
request
|
|
|
|
.headers()
|
|
|
|
.set("Accept", "application/json")
|
|
|
|
.map_err(|e| format!("{:?}", e))?;
|
2022-04-04 09:25:17 +00:00
|
|
|
|
2022-04-05 09:16:04 +00:00
|
|
|
Ok(request)
|
2022-04-04 09:25:17 +00:00
|
|
|
}
|
2022-04-06 04:39:12 +00:00
|
|
|
|
|
|
|
pub async fn send_to_backend(entries: HashMap<String, String>) -> Result<String, String> {
|
|
|
|
let mut send_json_string = String::from("{");
|
|
|
|
for (key, value) in entries {
|
|
|
|
send_json_string.push('"');
|
|
|
|
send_json_string.push_str(&key);
|
2022-04-06 09:43:17 +00:00
|
|
|
send_json_string.push_str("\":");
|
|
|
|
if key == "id" || key == "position" {
|
|
|
|
send_json_string.push_str(&value);
|
|
|
|
} else {
|
|
|
|
send_json_string.push('"');
|
|
|
|
send_json_string.push_str(&value);
|
|
|
|
send_json_string.push('"');
|
|
|
|
}
|
|
|
|
send_json_string.push(',');
|
2022-04-06 04:39:12 +00:00
|
|
|
}
|
|
|
|
send_json_string.truncate(send_json_string.len() - 1);
|
|
|
|
send_json_string.push('}');
|
|
|
|
|
|
|
|
// TODO check usage of "no-cors"
|
|
|
|
let function = Function::new_no_args(&format!(
|
|
|
|
"
|
|
|
|
let fetch_settings = {{}};
|
|
|
|
fetch_settings.method = 'POST';
|
|
|
|
fetch_settings.headers = {{}};
|
|
|
|
fetch_settings.headers['Content-Type'] = 'application/json';
|
|
|
|
fetch_settings.headers['Accept'] = 'text/html,application/json';
|
|
|
|
//fetch_settings.mode = 'no-cors';
|
|
|
|
fetch_settings.body = '{}';
|
|
|
|
|
|
|
|
return fetch('{}', fetch_settings)
|
|
|
|
.then((response) => {{
|
|
|
|
return response.text();
|
|
|
|
}});
|
|
|
|
",
|
|
|
|
send_json_string, BACKEND_URL,
|
|
|
|
));
|
|
|
|
|
|
|
|
let jsvalue: JsValue = function
|
|
|
|
.call0(&function)
|
|
|
|
.map_err(|e| format!("Failed to POST to backend: {:?}", e))?;
|
|
|
|
let promise: Promise = jsvalue.dyn_into().map_err(|e| {
|
|
|
|
format!(
|
|
|
|
"Failed to get Promise out of JsValue when POSTing to backend: {:?}",
|
|
|
|
e
|
|
|
|
)
|
|
|
|
})?;
|
|
|
|
let future_result: JsValue = JsFuture::from(promise)
|
|
|
|
.await
|
|
|
|
.map_err(|e| format!("Failed to await promise when POSTing to backend: {:?}", e))?;
|
|
|
|
|
|
|
|
let json_string = String::from(JsString::from(future_result));
|
|
|
|
|
|
|
|
Ok(json_string)
|
|
|
|
}
|