218 lines
6.8 KiB
Rust
218 lines
6.8 KiB
Rust
use plate_tool_lib::{plate::PlateType};
|
|
use uuid::Uuid;
|
|
use wasm_bindgen::{prelude::*, JsCast};
|
|
use web_sys::{
|
|
HtmlDialogElement, HtmlElement, HtmlOptionElement,
|
|
HtmlSelectElement,
|
|
};
|
|
|
|
use yew::prelude::*;
|
|
use yewdux::prelude::*;
|
|
|
|
use std::rc::Rc;
|
|
use std::str::FromStr;
|
|
|
|
use crate::components::callbacks::main_window_callbacks::create_close_button;
|
|
use crate::components::states::MainState;
|
|
|
|
pub fn merge_button_callback(main_dispatch: Dispatch<MainState>, id: Uuid) -> Callback<MouseEvent> {
|
|
Callback::from(move |_| {
|
|
let dialog_opt = create_merge_dialog(main_dispatch.clone(), id);
|
|
if let Some(dialog) = dialog_opt {
|
|
let window = web_sys::window().unwrap();
|
|
let document = window.document().unwrap();
|
|
let body = document.body().unwrap();
|
|
let _ = body.append_child(&dialog);
|
|
dialog.set_open(true);
|
|
}
|
|
})
|
|
}
|
|
|
|
fn create_merge_dialog(main_dispatch: Dispatch<MainState>, id: Uuid) -> Option<HtmlDialogElement> {
|
|
let other_plates = get_all_plates_except(main_dispatch.clone(), id);
|
|
if other_plates.is_empty() {
|
|
return None;
|
|
}
|
|
|
|
let dialog = create_dialog();
|
|
|
|
let select = create_select_for_plates(&other_plates);
|
|
dialog.append_child(&select).unwrap();
|
|
let select_rc = Rc::new(select);
|
|
let ok_button = create_ok_button(main_dispatch.clone(), select_rc.clone(), id);
|
|
dialog.append_child(&ok_button).unwrap();
|
|
|
|
Some(dialog)
|
|
}
|
|
|
|
fn create_dialog() -> HtmlDialogElement {
|
|
let window = web_sys::window().unwrap();
|
|
let document = window.document().unwrap();
|
|
|
|
let dialog = document
|
|
.create_element("dialog")
|
|
.unwrap()
|
|
.dyn_into::<HtmlDialogElement>()
|
|
.unwrap();
|
|
dialog.set_class_name("dialog shifted_dialog");
|
|
let onclose_callback = {
|
|
let dialog = dialog.clone();
|
|
Closure::<dyn FnMut(_)>::new(move |_: Event| {
|
|
dialog.remove();
|
|
})
|
|
};
|
|
dialog.set_onclose(Some(onclose_callback.as_ref().unchecked_ref()));
|
|
|
|
let close_button = create_close_button(&onclose_callback);
|
|
onclose_callback.forget();
|
|
dialog.append_child(&close_button).unwrap();
|
|
|
|
let header = document.create_element("h2").unwrap();
|
|
header.set_inner_html("Merge Plates");
|
|
dialog.append_child(&header).unwrap();
|
|
|
|
dialog
|
|
}
|
|
|
|
fn create_ok_button(
|
|
main_dispatch: Dispatch<MainState>,
|
|
select: Rc<HtmlSelectElement>,
|
|
id: Uuid,
|
|
) -> HtmlElement {
|
|
let window = web_sys::window().unwrap();
|
|
let document = window.document().unwrap();
|
|
|
|
let button = document
|
|
.create_element("button")
|
|
.unwrap()
|
|
.dyn_into::<HtmlElement>()
|
|
.unwrap();
|
|
button.set_inner_html("Ok");
|
|
let callback = ok_button_callback(main_dispatch, select, id);
|
|
button.set_onclick(Some(callback.as_ref().unchecked_ref()));
|
|
callback.forget();
|
|
|
|
button
|
|
}
|
|
|
|
fn ok_button_callback(
|
|
main_dispatch: Dispatch<MainState>,
|
|
select: Rc<HtmlSelectElement>,
|
|
to_id: Uuid,
|
|
) -> Closure<dyn FnMut(Event)> {
|
|
Closure::<dyn FnMut(_)>::new(move |_: Event| {
|
|
let selected = select
|
|
.selected_options()
|
|
.get_with_index(0)
|
|
.map(|el| el.dyn_into::<HtmlOptionElement>().unwrap())
|
|
.map(|opt_el| opt_el.value())
|
|
.and_then(|uuid_str| Uuid::from_str(&uuid_str).ok());
|
|
if let Some(from_id) = selected {
|
|
let plate_type = find_plate_type(main_dispatch.clone(), from_id).unwrap();
|
|
let binding = main_dispatch.get();
|
|
let merge_to = match plate_type {
|
|
PlateType::Source => binding.source_plates.iter().find(|x| x.get_uuid() == to_id).unwrap(),
|
|
PlateType::Destination => binding
|
|
.destination_plates
|
|
.iter()
|
|
.find(|x| x.get_uuid() == to_id).unwrap(),
|
|
};
|
|
|
|
main_dispatch.reduce_mut(|x| {
|
|
let merged_transfers = x.transfers.iter_mut().filter(|x| match plate_type {
|
|
PlateType::Source => x.source_id,
|
|
PlateType::Destination => x.dest_id
|
|
} == from_id);
|
|
|
|
for transfer in merged_transfers {
|
|
match plate_type {
|
|
PlateType::Source => {
|
|
transfer.source_id = to_id;
|
|
transfer.transfer_region.source_plate = merge_to.plate;
|
|
},
|
|
PlateType::Destination => {
|
|
transfer.dest_id = to_id;
|
|
transfer.transfer_region.dest_plate = merge_to.plate;
|
|
}
|
|
}
|
|
}
|
|
|
|
match plate_type {
|
|
PlateType::Source => x.source_plates.retain(|y| y.get_uuid() != from_id),
|
|
PlateType::Destination => x.destination_plates.retain(|y| y.get_uuid() != from_id)
|
|
};
|
|
});
|
|
}
|
|
})
|
|
}
|
|
|
|
fn create_select_for_plates(infos: &Vec<(Uuid, String)>) -> HtmlSelectElement {
|
|
let window = web_sys::window().unwrap();
|
|
let document = window.document().unwrap();
|
|
|
|
let select = document
|
|
.create_element("select")
|
|
.unwrap()
|
|
.dyn_into::<HtmlSelectElement>()
|
|
.unwrap();
|
|
for info in infos {
|
|
let _ = select.append_child(&create_option_for_plate(info));
|
|
}
|
|
|
|
select
|
|
}
|
|
|
|
fn create_option_for_plate(info: &(Uuid, String)) -> HtmlOptionElement {
|
|
let window = web_sys::window().unwrap();
|
|
let document = window.document().unwrap();
|
|
|
|
let opt = document
|
|
.create_element("option")
|
|
.unwrap()
|
|
.dyn_into::<HtmlOptionElement>()
|
|
.unwrap();
|
|
opt.set_value(&info.0.to_string());
|
|
opt.set_inner_text(&info.1);
|
|
|
|
opt
|
|
}
|
|
|
|
fn get_all_plates_except(main_dispatch: Dispatch<MainState>, id: Uuid) -> Vec<(Uuid, String)> {
|
|
let plate_type = find_plate_type(main_dispatch.clone(), id);
|
|
if plate_type.is_none() {
|
|
return Vec::new();
|
|
} // Return early if not found somehow
|
|
let plate_type = plate_type.unwrap();
|
|
|
|
let binding = main_dispatch.get();
|
|
let all_plates_iter = match plate_type {
|
|
PlateType::Source => binding.source_plates.iter(),
|
|
PlateType::Destination => binding.destination_plates.iter(),
|
|
};
|
|
|
|
all_plates_iter
|
|
.map(|x| (x.get_uuid(), x.name.to_string()))
|
|
.filter(|y| y.0 != id)
|
|
.collect()
|
|
}
|
|
|
|
fn find_plate_type(main_dispatch: Dispatch<MainState>, id: Uuid) -> Option<PlateType> {
|
|
if main_dispatch
|
|
.get()
|
|
.source_plates
|
|
.iter()
|
|
.any(|x| x.get_uuid() == id)
|
|
{
|
|
Some(PlateType::Source)
|
|
} else if main_dispatch
|
|
.get()
|
|
.destination_plates
|
|
.iter()
|
|
.any(|x| x.get_uuid() == id)
|
|
{
|
|
return Some(PlateType::Destination);
|
|
} else {
|
|
return None;
|
|
}
|
|
}
|