Merge plates
	
		
			
	
		
	
	
		
			
				
	
				Gitea Scan/plate-tool/pipeline/head This commit looks good
				
					Details
				
			
		
	
				
					
				
			
				
	
				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:
		
							parent
							
								
									0ec29f6783
								
							
						
					
					
						commit
						12684c0eea
					
				| 
						 | 
					@ -36,6 +36,12 @@ dialog > form[method="dialog"] {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.shifted_dialog {
 | 
				
			||||||
 | 
						top: 50vh;
 | 
				
			||||||
 | 
						left: 50vw;
 | 
				
			||||||
 | 
						margin: 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.close_button {
 | 
					.close_button {
 | 
				
			||||||
	color: red;
 | 
						color: red;
 | 
				
			||||||
	position: absolute;
 | 
						position: absolute;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,7 +5,7 @@ mod settings_callbacks;
 | 
				
			||||||
mod plate_edits_callbacks;
 | 
					mod plate_edits_callbacks;
 | 
				
			||||||
mod util;
 | 
					mod util;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use util::*;
 | 
					pub use util::*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub use export_callbacks::*;
 | 
					pub use export_callbacks::*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,9 @@
 | 
				
			||||||
mod select_callbacks;
 | 
					mod select_callbacks;
 | 
				
			||||||
mod info_dialog_callbacks;
 | 
					mod info_dialog_callbacks;
 | 
				
			||||||
 | 
					mod merge_callbacks;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub use select_callbacks::*;
 | 
					pub use select_callbacks::*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub use info_dialog_callbacks::*;
 | 
					pub use info_dialog_callbacks::*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub use merge_callbacks::*;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -181,6 +181,11 @@ fn PlateInfoModal(props: &PlateInfoModalProps) -> Html {
 | 
				
			||||||
        move |_| dialog_close_callback.emit(())
 | 
					        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 rename_onchange = tree_callbacks::rename_onchange(props.id, main_dispatch.clone());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let format_onchange = tree_callbacks::format_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! {
 | 
					    html! {
 | 
				
			||||||
        <dialog ref={dialog_ref} class="dialog" onclose={onclose}>
 | 
					        <dialog ref={dialog_ref} class="dialog" onclose={onclose}>
 | 
				
			||||||
            <h2>{"Plate Info"}</h2>
 | 
					            <h2>{"Plate Info"}</h2>
 | 
				
			||||||
| 
						 | 
					@ -219,6 +229,7 @@ fn PlateInfoModal(props: &PlateInfoModalProps) -> Html {
 | 
				
			||||||
            { for plate_format_options }
 | 
					            { for plate_format_options }
 | 
				
			||||||
            </select>
 | 
					            </select>
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            <button onclick={merge_button_callback} onclick={onclose_secondary}>{"Merge"}</button>
 | 
				
			||||||
            <form class="modal_close" method="dialog"><button /></form>
 | 
					            <form class="modal_close" method="dialog"><button /></form>
 | 
				
			||||||
        </dialog>
 | 
					        </dialog>
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue