From 12684c0eea798436f45be6737f8d4968e1b9c487 Mon Sep 17 00:00:00 2001 From: Emilia Date: Tue, 20 Feb 2024 23:31:56 -0500 Subject: [PATCH] Merge plates i wrote this so late it probably does not work ughhhhhhhhh --- .../default_theme/components/_dialog.scss | 6 + .../callbacks/main_window_callbacks/mod.rs | 2 +- .../tree_callbacks/merge_callbacks.rs | 217 ++++++++++++++++++ .../callbacks/tree_callbacks/mod.rs | 3 + plate-tool-web/src/components/tree.rs | 11 + 5 files changed, 238 insertions(+), 1 deletion(-) create mode 100644 plate-tool-web/src/components/callbacks/tree_callbacks/merge_callbacks.rs diff --git a/plate-tool-web/assets/scss/default_theme/components/_dialog.scss b/plate-tool-web/assets/scss/default_theme/components/_dialog.scss index 6aad48d..ef8d287 100644 --- a/plate-tool-web/assets/scss/default_theme/components/_dialog.scss +++ b/plate-tool-web/assets/scss/default_theme/components/_dialog.scss @@ -36,6 +36,12 @@ dialog > form[method="dialog"] { } } +.shifted_dialog { + top: 50vh; + left: 50vw; + margin: 0; +} + .close_button { color: red; position: absolute; diff --git a/plate-tool-web/src/components/callbacks/main_window_callbacks/mod.rs b/plate-tool-web/src/components/callbacks/main_window_callbacks/mod.rs index d9ec7b2..5d0ff12 100644 --- a/plate-tool-web/src/components/callbacks/main_window_callbacks/mod.rs +++ b/plate-tool-web/src/components/callbacks/main_window_callbacks/mod.rs @@ -5,7 +5,7 @@ mod settings_callbacks; mod plate_edits_callbacks; mod util; -use util::*; +pub use util::*; pub use export_callbacks::*; diff --git a/plate-tool-web/src/components/callbacks/tree_callbacks/merge_callbacks.rs b/plate-tool-web/src/components/callbacks/tree_callbacks/merge_callbacks.rs new file mode 100644 index 0000000..d34ff4e --- /dev/null +++ b/plate-tool-web/src/components/callbacks/tree_callbacks/merge_callbacks.rs @@ -0,0 +1,217 @@ +use plate_tool_lib::{plate::PlateType, plate_instances::PlateInstance}; +use uuid::Uuid; +use wasm_bindgen::{prelude::*, JsCast}; +use web_sys::{ + HtmlDialogElement, HtmlElement, HtmlFormElement, HtmlInputElement, 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, id: Uuid) -> Callback { + 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, id: Uuid) -> Option { + 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::() + .unwrap(); + dialog.set_class_name("dialog shifted_dialog"); + let onclose_callback = { + let dialog = dialog.clone(); + Closure::::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, + select: Rc, + id: Uuid, +) -> HtmlElement { + let window = web_sys::window().unwrap(); + let document = window.document().unwrap(); + + let button = document + .create_element("button") + .unwrap() + .dyn_into::() + .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, + select: Rc, + to_id: Uuid, +) -> Closure { + Closure::::new(move |_: Event| { + let selected = select + .selected_options() + .get_with_index(0) + .map(|el| el.dyn_into::().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::() + .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::() + .unwrap(); + opt.set_value(&info.0.to_string()); + opt.set_inner_text(&info.1); + + opt +} + +fn get_all_plates_except(main_dispatch: Dispatch, 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, id: Uuid) -> Option { + if main_dispatch + .get() + .source_plates + .iter() + .any(|x| x.get_uuid() == id) + { + return Some(PlateType::Source); + } else if main_dispatch + .get() + .destination_plates + .iter() + .any(|x| x.get_uuid() == id) + { + return Some(PlateType::Destination); + } else { + return None; + } +} diff --git a/plate-tool-web/src/components/callbacks/tree_callbacks/mod.rs b/plate-tool-web/src/components/callbacks/tree_callbacks/mod.rs index 7d60f88..05e475d 100644 --- a/plate-tool-web/src/components/callbacks/tree_callbacks/mod.rs +++ b/plate-tool-web/src/components/callbacks/tree_callbacks/mod.rs @@ -1,6 +1,9 @@ mod select_callbacks; mod info_dialog_callbacks; +mod merge_callbacks; pub use select_callbacks::*; pub use info_dialog_callbacks::*; + +pub use merge_callbacks::*; diff --git a/plate-tool-web/src/components/tree.rs b/plate-tool-web/src/components/tree.rs index 92fda96..de055fe 100644 --- a/plate-tool-web/src/components/tree.rs +++ b/plate-tool-web/src/components/tree.rs @@ -181,6 +181,11 @@ fn PlateInfoModal(props: &PlateInfoModalProps) -> Html { move |_| dialog_close_callback.emit(()) }; + let onclose_secondary = { + let dialog_close_callback = props.dialog_close_callback.clone(); + move |_| dialog_close_callback.emit(()) + }; + let rename_onchange = tree_callbacks::rename_onchange(props.id, main_dispatch.clone()); let format_onchange = tree_callbacks::format_onchange(props.id, main_dispatch.clone()); @@ -209,6 +214,11 @@ fn PlateInfoModal(props: &PlateInfoModalProps) -> Html { ); } + let merge_button_callback = { + let main_dispatch = main_dispatch.clone(); + tree_callbacks::merge_button_callback(main_dispatch, props.id) + }; + html! {

{"Plate Info"}

@@ -219,6 +229,7 @@ fn PlateInfoModal(props: &PlateInfoModalProps) -> Html { { for plate_format_options } } +
}