Merge plates
Gitea Scan/plate-tool/pipeline/head This commit looks good Details

i wrote this so late it probably does not work ughhhhhhhhh
This commit is contained in:
Emilia Allison 2024-02-20 23:31:56 -05:00
parent 0ec29f6783
commit 12684c0eea
Signed by: emilia
GPG Key ID: 05D5D1107E5100A1
5 changed files with 238 additions and 1 deletions

View File

@ -36,6 +36,12 @@ dialog > form[method="dialog"] {
}
}
.shifted_dialog {
top: 50vh;
left: 50vw;
margin: 0;
}
.close_button {
color: red;
position: absolute;

View File

@ -5,7 +5,7 @@ mod settings_callbacks;
mod plate_edits_callbacks;
mod util;
use util::*;
pub use util::*;
pub use export_callbacks::*;

View File

@ -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<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)
{
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;
}
}

View File

@ -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::*;

View File

@ -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! {
<dialog ref={dialog_ref} class="dialog" onclose={onclose}>
<h2>{"Plate Info"}</h2>
@ -219,6 +229,7 @@ fn PlateInfoModal(props: &PlateInfoModalProps) -> Html {
{ for plate_format_options }
</select>
}
<button onclick={merge_button_callback} onclick={onclose_secondary}>{"Merge"}</button>
<form class="modal_close" method="dialog"><button /></form>
</dialog>
}