plate-tool/src/components/tree.rs

191 lines
6.5 KiB
Rust
Raw Normal View History

2023-05-21 16:45:12 +00:00
#![allow(non_snake_case)]
2023-05-24 01:08:32 +00:00
use uuid::Uuid;
use wasm_bindgen::JsCast;
use web_sys::{EventTarget, HtmlElement, HtmlDialogElement};
use yew::prelude::*;
use yewdux::prelude::*;
use crate::data::{plate_instances::PlateInstance, transfer::Transfer};
use crate::data::plate::*;
2023-05-24 15:20:12 +00:00
use crate::components::states::{MainState, NewTransferState};
2023-05-21 16:45:12 +00:00
2023-05-22 22:31:02 +00:00
#[derive(PartialEq, Properties)]
pub struct TreeProps {
pub open_new_plate_callback: Callback<()>,
}
#[function_component]
2023-05-22 22:31:02 +00:00
pub fn Tree(props: &TreeProps) -> Html {
2023-05-24 15:20:12 +00:00
let (main_state, main_dispatch) = use_store::<MainState>();
let (selection_state, selection_dispatch) = use_store::<NewTransferState>();
let plate_modal_id: UseStateHandle<Option<Uuid>> = use_state(|| {None});
2023-05-24 01:08:32 +00:00
let open_plate_info_callback = {
2023-05-24 15:20:12 +00:00
let plate_menu_id =plate_modal_id.clone();
2023-05-24 01:08:32 +00:00
Callback::from(move |e: MouseEvent| {
let target: Option<EventTarget> = e.target();
let li = target.and_then(|t| t.dyn_into::<HtmlElement>().ok());
if let Some(li) = li {
if let Ok(id) = u128::from_str_radix(li.id().as_str(), 10) {
plate_menu_id.set(Some(Uuid::from_u128(id)));
}
}
})
};
let plate_info_close_callback = {
2023-05-24 15:20:12 +00:00
let plate_menu_id =plate_modal_id.clone();
2023-05-24 01:08:32 +00:00
Callback::from(move |_| {
plate_menu_id.set(None);
})
};
let plate_info_delete_callback = {
2023-05-24 15:20:12 +00:00
let dispatch = main_dispatch.clone();
let plate_menu_id = plate_modal_id.clone();
2023-05-24 01:08:32 +00:00
Callback::from(move |_| {
if let Some(id) = *plate_menu_id {
dispatch.reduce_mut(|state| {
state.del_plate(id);
});
}
})
};
2023-05-24 15:20:12 +00:00
let source_plate_select_callback = {
let dispatch = selection_dispatch.clone();
Callback::from(move |e: MouseEvent| {
let target: Option<EventTarget> = e.target();
let li = target.and_then(|t| t.dyn_into::<HtmlElement>().ok());
if let Some(li) = li {
if let Ok(id) = u128::from_str_radix(li.id().as_str(), 10) {
dispatch.reduce_mut(|state| state.source_id = Uuid::from_u128(id))
}
}
})
};
let destination_plate_select_callback = {
let dispatch = selection_dispatch.clone();
Callback::from(move |e: MouseEvent| {
let target: Option<EventTarget> = e.target();
let li = target.and_then(|t| t.dyn_into::<HtmlElement>().ok());
if let Some(li) = li {
if let Ok(id) = u128::from_str_radix(li.id().as_str(), 10) {
dispatch.reduce_mut(|state| state.destination_id = Uuid::from_u128(id))
}
}
})
};
2023-05-24 01:08:32 +00:00
2023-05-24 15:20:12 +00:00
let source_plates = main_state.source_plates.iter()
.map(|spi| {
2023-05-24 01:08:32 +00:00
html!{ <li id={spi.get_uuid().as_u128().to_string()}
2023-05-24 15:20:12 +00:00
ondblclick={open_plate_info_callback.clone()}
onclick={source_plate_select_callback.clone()}
class={classes!(
Some(if spi.get_uuid() == selection_state.source_id {Some("selected")}
else {None})
)}>
{String::from(spi)}
</li> }
}).collect::<Html>();
2023-05-24 15:20:12 +00:00
let dest_plates = main_state.destination_plates.iter()
.map(|dpi| {
html!{ <li id={dpi.get_uuid().as_u128().to_string()}
ondblclick={open_plate_info_callback.clone()}
onclick={destination_plate_select_callback.clone()}
class={classes!(
Some(if dpi.get_uuid() == selection_state.destination_id {Some("selected")}
else {None})
)}> {String::from(dpi)} </li> }
}).collect::<Html>();
html! {
<div class="tree">
<div id="source-plates">
<h3>{"Source Plates:"}</h3>
<ul>
{source_plates}
</ul>
</div>
<div id="destination-plates">
<h3>{"Destination Plates:"}</h3>
<ul>
{dest_plates}
</ul>
</div>
<div id="transfers">
<h3>{"Transfers:"}</h3>
<ul>
</ul>
</div>
2023-05-24 15:20:12 +00:00
if let Some(id) = *plate_modal_id {
2023-05-24 01:08:32 +00:00
<PlateInfoModal id={id} dialog_close_callback={plate_info_close_callback}
delete_button_callback={plate_info_delete_callback}/>
}
// Temporary
<div>
2023-05-22 22:31:02 +00:00
<button type="button"
onclick={
let open_new_plate_callback = props.open_new_plate_callback.clone();
move |_| {open_new_plate_callback.emit(())}
}>
{"New Plate"}</button>
</div>
</div>
}
2023-05-21 16:45:12 +00:00
}
2023-05-24 01:08:32 +00:00
#[derive(PartialEq, Properties)]
struct PlateInfoModalProps {
id: Uuid,
dialog_close_callback: Callback<()>,
delete_button_callback: Callback<()>,
}
#[function_component]
fn PlateInfoModal(props: &PlateInfoModalProps) -> Html {
let (state, dispatch) = use_store::<MainState>();
let dialog_ref = use_node_ref();
let mut plate = state.source_plates.iter()
.find(|spi| {spi.get_uuid() == props.id});
if plate == None {
plate = state.destination_plates.iter()
.find(|dpi| {dpi.get_uuid() == props.id});
}
let plate_name = match plate {
Some(plate) => plate.name.clone(),
None => "Not Found".to_string()
};
let onclose = {
let dialog_close_callback = props.dialog_close_callback.clone();
move |_| {dialog_close_callback.emit(())}
};
let delete_onclick = {
let delete_button_callback = props.delete_button_callback.clone();
let dialog_ref = dialog_ref.clone();
move |_| {
delete_button_callback.emit(());
dialog_ref.cast::<HtmlDialogElement>().unwrap().close();
}
};
{
let dialog_ref = dialog_ref.clone();
use_effect_with_deps(|dialog_ref| {
dialog_ref.cast::<HtmlDialogElement>().unwrap().show_modal().ok();
},
dialog_ref);
}
html! {
<dialog ref={dialog_ref} class="dialog" onclose={onclose}>
<h2>{"Plate Info"}</h2>
<h3>{"Name: "}<input type="text" value={plate_name} /></h3>
<button onclick={delete_onclick}>{"Delete"}</button>
</dialog>
}
}