edc_web_components/pages/
common_expression_language_page.rs1use crate::components::ListCommonExpressionLanguage;
2use crate::contexts::{
3 CelExpressionLibraryItem, use_cel_expression_library_context, use_edc_connector_context,
4};
5use crate::models::CommonExpressionLanguageItem;
6use edc_connector_client::EdcConnectorApiVersion;
7use edc_connector_client::types::common_expression_language::NewCommonExpressionLanguage;
8use edc_connector_client::types::query::Query;
9use log::error;
10use patternfly_yew::prelude::*;
11use yew::platform::spawn_local;
12use yew::prelude::*;
13use yew::suspense::use_future_with;
14
15#[derive(Clone, Debug, PartialEq, Properties)]
16pub struct CommonExpressionLanguagePageProps {
17 pub on_new_cel: Callback<()>,
18 #[prop_or("Common Expression Language Library".to_string())]
19 pub title: String,
20 #[prop_or(None)]
21 pub tag_line: Option<String>,
22 #[prop_or("Create a CEL Expression".to_string())]
23 pub create_title: String,
24 #[prop_or("Show Library".to_string())]
25 pub open_library_title: String,
26}
27#[component]
28pub fn CommonExpressionLanguagePage(props: &CommonExpressionLanguagePageProps) -> Html {
29 let refresh = use_state(|| 0usize);
30 let offset = use_state(|| 0usize);
31 let limit = use_state(|| 10usize);
32
33 let onoffset = use_callback(
34 (refresh.clone(), offset.setter()),
35 |offset, (refresh, offset_setter)| {
36 offset_setter.set(offset);
37 refresh.set(**refresh + 1);
38 },
39 );
40
41 let onlimit = use_callback(
42 (refresh.clone(), limit.setter()),
43 |limit, (refresh, limit_setter)| {
44 limit_setter.set(limit);
45 refresh.set(**refresh + 1);
46 },
47 );
48
49 let edc_connector_context = use_edc_connector_context();
50
51 let ondelete = use_callback(
52 (refresh.clone(), edc_connector_context.clone()),
53 |asset_id: String, (refresh, edc_connector_context)| {
54 let refresh = refresh.clone();
55 let edc_connector_context = edc_connector_context.clone();
56 let asset_id = asset_id.clone();
57
58 spawn_local(async move {
59 if let Some(client) = edc_connector_context.get_client() {
60 let _ = client
61 .common_expression_language(EdcConnectorApiVersion::V5Beta)
62 .delete(&asset_id)
63 .await;
64 }
65 refresh.set(*refresh + 1);
66 });
67 },
68 );
69
70 let tag_line = props
71 .tag_line
72 .as_ref()
73 .map(|tag_line| html!(<p>{ tag_line }</p>))
74 .unwrap_or_default();
75
76 let cel_expression_library_context = use_cel_expression_library_context();
77
78 let expanded = use_state_eq(|| false);
79 let onclick = use_callback(expanded.clone(), |_, expanded| {
80 expanded.set(!**expanded);
81 });
82
83 let cel_expression_library = cel_expression_library_context.as_ref().map(|_| {
84 html_nested!(
85 <SplitItem>
86 <Button icon={Icon::Catalog} {onclick} variant={ButtonVariant::Secondary}>
87 { &props.open_library_title }
88 </Button>
89 </SplitItem>
90 )
91 });
92
93 let import_cel_expression = use_callback(
94 (edc_connector_context.clone(), refresh.clone()),
95 |cel_expression_library_item: CelExpressionLibraryItem, (edc_connector_context, refresh)| {
96 let edc_connector_context = edc_connector_context.clone();
97 let refresh = refresh.clone();
98
99 let new_cel_builder = NewCommonExpressionLanguage::builder()
100 .left_operand(cel_expression_library_item.left_operand.to_string())
101 .description(cel_expression_library_item.description.unwrap_or_default())
102 .scopes(cel_expression_library_item.scopes)
103 .expression(cel_expression_library_item.expression);
104
105 let new_cel = new_cel_builder.build();
106
107 spawn_local(async move {
108 if let Some(client) = edc_connector_context.get_client() {
109 match client
110 .common_expression_language(EdcConnectorApiVersion::V5Beta)
111 .create(&new_cel)
112 .await
113 {
114 Ok(_) => {
115 refresh.set(*refresh + 1);
116 }
117 Err(error) => {
118 error!("Failed to import CEL expression: {}", error);
119 }
120 }
121 }
122 })
123 },
124 );
125
126 let panel_content = cel_expression_library_context.clone().map(move |cel_expression_library| {
127 let items =
128 cel_expression_library.cel_expression_library().iter().map(|item| {
129 let name = item.name.to_string();
130 let item = item.clone();
131
132 html!(
133 <StackItem>
134 <Button
135 variant={ButtonVariant::Control}
136 icon={Icon::Import}
137 onclick={import_cel_expression.reform(move |_| item.clone())}
138 >
139 { name }
140 </Button>
141 </StackItem>
142 )
143 });
144
145 html!(
146 <Panel>
147 <PanelHeader>{ "CEL Expression Library" }</PanelHeader>
148 <PanelMain>
149 <PanelMainBody>
150 <Stack gutter=true>{ for items }</Stack>
151 </PanelMainBody>
152 </PanelMain>
153 </Panel>
154 )
155 });
156
157 html!(
158 <Stack gutter=true>
159 <StackItem>
160 <Split gutter=true>
161 <SplitItem fill=true>
162 <Title level={Level::H3} size={Size::XXLarge}>{ &props.title }</Title>
163 { tag_line }
164 </SplitItem>
165 { cel_expression_library }
166 <SplitItem>
167 <Button
168 icon={Icon::Plus}
169 onclick={props.on_new_cel.reform(|_| ())}
170 variant={ButtonVariant::Primary}
171 >
172 { &props.create_title }
173 </Button>
174 </SplitItem>
175 </Split>
176 </StackItem>
177 <StackItem>
178 <Drawer expanded={*expanded} inline=true>
179 <DrawerContent {panel_content}>
180 <DrawerContentBody>
181 <Suspense>
182 <CommonExpressionLanguagePageInner
183 offset={*offset}
184 limit={*limit}
185 {onoffset}
186 {onlimit}
187 {ondelete}
188 force_refresh={*refresh}
189 />
190 </Suspense>
191 </DrawerContentBody>
192 </DrawerContent>
193 </Drawer>
194 </StackItem>
195 </Stack>
196 )
197}
198
199#[derive(Clone, Debug, PartialEq, Properties)]
200pub struct CommonExpressionLanguagePageInnerProps {
201 pub offset: usize,
202 pub limit: usize,
203 pub onoffset: Callback<usize>,
204 pub onlimit: Callback<usize>,
205 pub ondelete: Callback<String>,
206 pub force_refresh: usize,
207}
208
209#[component]
210pub fn CommonExpressionLanguagePageInner(
211 props: &CommonExpressionLanguagePageInnerProps,
212) -> HtmlResult {
213 let edc_connector_context = use_edc_connector_context();
214
215 let common_expression_language_items = use_future_with(
216 (
217 edc_connector_context,
218 props.limit,
219 props.offset,
220 props.force_refresh,
221 ),
222 |parameters| async move {
223 let (edc_connector_context, limit, offset, _) = (*parameters).clone();
224
225 let query = Query::builder()
226 .limit(limit as u32)
227 .offset(offset as u32)
228 .build();
230
231 if let Some(client) = edc_connector_context.get_client() {
232 client
233 .common_expression_language(EdcConnectorApiVersion::V5Beta)
234 .query(query)
235 .await
236 .map_err(|error| {
237 log::error!("Error: {}", error);
238 error
239 })
240 .unwrap_or_default()
241 .into_iter()
242 .map(CommonExpressionLanguageItem::from)
243 .collect::<Vec<_>>()
244 } else {
245 vec![]
246 }
247 },
248 )?;
249
250 let common_expression_language_items = (*common_expression_language_items).clone();
251
252 Ok(html!(
253 <ListCommonExpressionLanguage
254 common_expression_language_items={common_expression_language_items}
255 offset={props.offset}
256 limit={props.limit}
257 onoffset={props.onoffset.clone()}
258 onlimit={props.onlimit.clone()}
259 ondelete={props.ondelete.clone()}
260 />
261 ))
262}