mcai_workflow/worker_details_panel/
panel.rs

1use crate::SharedWorkerDefinition;
2use css_in_rust_next::Style;
3use schemars::schema::{InstanceType, Schema, SchemaObject, SingleOrVec};
4use web_sys::Node;
5use yew::virtual_dom::VNode;
6use yew::{html, Component, Context, Html, Properties};
7
8#[derive(PartialEq, Properties)]
9pub struct WorkerDetailsPanelProperties {
10  pub height: String,
11  pub width: String,
12  pub worker_definition: SharedWorkerDefinition,
13}
14
15pub struct WorkerDetailsPanel {
16  style: Style,
17}
18
19impl Component for WorkerDetailsPanel {
20  type Message = ();
21  type Properties = WorkerDetailsPanelProperties;
22
23  fn create(_ctx: &Context<Self>) -> Self {
24    let style = Style::create("Component", include_str!("panel.css")).unwrap();
25    Self { style }
26  }
27
28  fn view(&self, ctx: &Context<Self>) -> Html {
29    let style = format!(
30      "height: {}; width: {};",
31      ctx.props().height,
32      ctx.props().width,
33    );
34
35    let worker = ctx.props().worker_definition.lock().unwrap();
36
37    let description = web_sys::window()
38      .unwrap()
39      .document()
40      .unwrap()
41      .create_element("div")
42      .unwrap();
43
44    description.set_inner_html(&worker.description.description.replace('\n', "<br/>"));
45
46    let description = VNode::VRef(Node::from(description));
47
48    let parameters: Html = worker
49      .parameters
50      .schema
51      .object
52      .as_ref()
53      .unwrap()
54      .properties
55      .iter()
56      .map(|(key, kind)| {
57        let (parameter_title, parameter_type) = match kind {
58          Schema::Object(SchemaObject {
59            metadata,
60            instance_type: Some(SingleOrVec::Single(instance_type)),
61            ..
62          }) => {
63            let kind = match *instance_type.as_ref() {
64              InstanceType::String => "String",
65              InstanceType::Boolean => "Boolean",
66              InstanceType::Array => "Array",
67              InstanceType::Integer => "Integer",
68              InstanceType::Number => "Number",
69              InstanceType::Object => "Object",
70              InstanceType::Null => "Null",
71            };
72
73            let title: String = metadata
74              .as_ref()
75              .and_then(|metadata| metadata.title.clone())
76              .unwrap_or_default();
77
78            (html!(title), html!(kind))
79          }
80          Schema::Object(SchemaObject {
81            metadata,
82            instance_type: Some(SingleOrVec::Vec(instance_type)),
83            ..
84          }) => {
85            let mut kinds = instance_type
86              .iter()
87              .filter(|kind| kind != &&InstanceType::Null)
88              .map(|kind| match *kind {
89                InstanceType::String => "String",
90                InstanceType::Boolean => "Boolean",
91                InstanceType::Array => "Array",
92                InstanceType::Integer => "Integer",
93                InstanceType::Number => "Number",
94                InstanceType::Object => "Object",
95                InstanceType::Null => "Null",
96              })
97              .collect::<Vec<&str>>()
98              .join(", ");
99
100            if instance_type.contains(&InstanceType::Null) {
101              kinds += " (optional)";
102            }
103
104            let title: String = metadata
105              .as_ref()
106              .and_then(|metadata| metadata.title.clone())
107              .unwrap_or_default();
108
109            (html!(title), html!({ kinds }))
110          }
111          _ => (html!(""), html!({ "Complex type" })),
112        };
113
114        html!(
115          <div class="field">
116            <label>
117              {key}
118              <span class="type">
119                {parameter_type}
120              </span>
121            </label>
122            <span class="description">
123              {parameter_title}
124            </span>
125          </div>
126        )
127      })
128      .collect();
129
130    html!(
131      <span class={self.style.clone()} style={style}>
132        <div class="title">
133          <label>{format!("Worker {}", worker.description.label)}</label>
134        </div>
135
136        <div class="content">
137          <div class="field">
138            <label>
139              {"Short description"}
140            </label>
141            <span>
142              <div class="description">
143                {{&worker.description.short_description}}
144              </div>
145            </span>
146          </div>
147          <div class="field">
148            <label>
149              {"Description"}
150            </label>
151            <span>
152              <div class="description">
153                {description}
154              </div>
155            </span>
156          </div>
157          <div class="field">
158            <label>
159              {"Version"}
160            </label>
161            <span>
162              {{&worker.description.version}}
163            </span>
164          </div>
165          <div class="field">
166            <label>
167              {"SDK Version"}
168            </label>
169            <span>
170              {{&worker.description.sdk_version}}
171            </span>
172          </div>
173          <h2>{"Parameters"}</h2>
174          {parameters}
175        </div>
176      </span>
177    )
178  }
179}