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