mcai_workflow/components/edit_parameter/
edit_requirements.rs1use crate::{ActionButton, Button, Modal, ModalMessage};
2use css_in_rust_next::Style;
3use mcai_models::Requirement;
4use wasm_bindgen::JsCast;
5use web_sys::{Event, EventTarget, HtmlInputElement};
6use yew::{html, Callback, Component, Context, Html, Properties};
7use yew_feather::{plus::Plus, trash_2::Trash2};
8
9#[derive(PartialEq, Properties)]
10pub struct EditRequirementProperties {
11 pub title: String,
12 pub field_name: String,
13 pub event: Callback<EditRequirementMessage>,
14 pub requirement: Option<Requirement>,
15}
16
17pub enum EditRequirementMessage {
18 Submit(Option<Requirement>),
19 Cancel,
20}
21pub enum InternalMessage {
22 AddPath,
23 DeletePath(usize),
24 UpdatePath((usize, String)),
25 Modal(ModalMessage),
26}
27
28pub struct EditRequirement {
29 style: Style,
30 requirement: Option<Requirement>,
31}
32
33impl Component for EditRequirement {
34 type Message = InternalMessage;
35 type Properties = EditRequirementProperties;
36
37 fn create(ctx: &Context<Self>) -> Self {
38 let style = Style::create(
39 "Component",
40 concat!(
41 include_str!("edit_style.css"),
42 include_str!("edit_requirements.css")
43 ),
44 )
45 .unwrap();
46
47 let requirement = ctx.props().requirement.clone();
48 Self { style, requirement }
49 }
50
51 fn update(&mut self, ctx: &Context<Self>, msg: Self::Message) -> bool {
52 match msg {
53 InternalMessage::AddPath => {
54 if let Some(requirement) = &mut self.requirement {
55 requirement.paths.push("".to_string())
56 } else {
57 self.requirement = Some(Requirement {
58 paths: vec!["".to_string()],
59 })
60 }
61 true
62 }
63 InternalMessage::DeletePath(index) => {
64 if let Some(requirement) = &mut self.requirement {
65 requirement.paths.remove(index);
66 }
67 true
68 }
69 InternalMessage::UpdatePath((index, value)) => {
70 if let Some(requirement) = &mut self.requirement {
71 requirement.paths[index] = value;
72 }
73 false
74 }
75 InternalMessage::Modal(message) => {
76 let event = match message {
77 ModalMessage::Submit | ModalMessage::Update => {
78 Some(EditRequirementMessage::Submit(self.requirement.clone()))
79 }
80 ModalMessage::Cancel => Some(EditRequirementMessage::Cancel),
81 ModalMessage::Delete => None,
82 };
83
84 if let Some(event) = event {
85 ctx.props().event.emit(event)
86 }
87 false
88 }
89 }
90 }
91
92 fn view(&self, ctx: &Context<Self>) -> Html {
93 let action_buttons = vec![ActionButton::Submit(true)];
94
95 let inner: Html = self
96 .requirement
97 .as_ref()
98 .map(|requirement| {
99 requirement
100 .paths
101 .iter()
102 .enumerate()
103 .map(|(index, value)| {
104 let cloned_index = index;
105
106 let callback = ctx.link().batch_callback(move |e: Event| {
107 let target: Option<EventTarget> = e.target();
108 let input = target.and_then(|t| t.dyn_into::<HtmlInputElement>().ok());
109 input.map(|input| InternalMessage::UpdatePath((cloned_index, input.value())))
110 });
111
112 html!(
113 <div class="item">
114 <input type="text" value={value.clone()} onchange={callback} />
115 <Button
116 label=""
117 icon={html!(<Trash2 />)}
118 onclick={ctx.link().callback(move |_| InternalMessage::DeletePath(index))}
119 />
120 </div>
121 )
122 })
123 .collect()
124 })
125 .unwrap_or_default();
126
127 html!(
128 <Modal
129 event={ctx.link().callback(InternalMessage::Modal)}
130 height="50vh" width="19vw"
131 modal_title={ctx.props().title.clone()}
132 actions={action_buttons}>
133 <div class={self.style.clone()}>
134 {"Paths"}
135 {inner}
136 <div class="add">
137 <Button
138 label="Add an another path"
139 icon={html!(<Plus />)}
140 onclick={ctx.link().callback(|_| InternalMessage::AddPath)}
141 />
142 </div>
143 </div>
144 </Modal>
145 )
146 }
147}