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
127 .clone()
128 .map(move |cel_expression_library| {
129 let items = cel_expression_library
130 .cel_expression_library()
131 .iter()
132 .map(|item| {
133 let name = item.name.to_string();
134 let item = item.clone();
135
136 html!(
137 <StackItem>
138 <Button
139 variant={ButtonVariant::Control}
140 icon={Icon::Import}
141 onclick={import_cel_expression.reform(move |_| item.clone())}
142 >
143 { name }
144 </Button>
145 </StackItem>
146 )
147 });
148
149 html!(
150 <Panel>
151 <PanelHeader>{ "CEL Expression Library" }</PanelHeader>
152 <PanelMain>
153 <PanelMainBody>
154 <Stack gutter=true>{ for items }</Stack>
155 </PanelMainBody>
156 </PanelMain>
157 </Panel>
158 )
159 });
160
161 html!(
162 <Stack gutter=true>
163 <StackItem>
164 <Split gutter=true>
165 <SplitItem fill=true>
166 <Title level={Level::H3} size={Size::XXLarge}>{ &props.title }</Title>
167 { tag_line }
168 </SplitItem>
169 { cel_expression_library }
170 <SplitItem>
171 <Button
172 icon={Icon::Plus}
173 onclick={props.on_new_cel.reform(|_| ())}
174 variant={ButtonVariant::Primary}
175 >
176 { &props.create_title }
177 </Button>
178 </SplitItem>
179 </Split>
180 </StackItem>
181 <StackItem>
182 <Drawer expanded={*expanded} inline=true>
183 <DrawerContent {panel_content}>
184 <DrawerContentBody>
185 <Suspense>
186 <CommonExpressionLanguagePageInner
187 offset={*offset}
188 limit={*limit}
189 {onoffset}
190 {onlimit}
191 {ondelete}
192 force_refresh={*refresh}
193 />
194 </Suspense>
195 </DrawerContentBody>
196 </DrawerContent>
197 </Drawer>
198 </StackItem>
199 </Stack>
200 )
201}
202
203#[derive(Clone, Debug, PartialEq, Properties)]
204pub struct CommonExpressionLanguagePageInnerProps {
205 pub offset: usize,
206 pub limit: usize,
207 pub onoffset: Callback<usize>,
208 pub onlimit: Callback<usize>,
209 pub ondelete: Callback<String>,
210 pub force_refresh: usize,
211}
212
213#[component]
214pub fn CommonExpressionLanguagePageInner(
215 props: &CommonExpressionLanguagePageInnerProps,
216) -> HtmlResult {
217 let edc_connector_context = use_edc_connector_context();
218
219 let common_expression_language_items = use_future_with(
220 (
221 edc_connector_context,
222 props.limit,
223 props.offset,
224 props.force_refresh,
225 ),
226 |parameters| async move {
227 let (edc_connector_context, limit, offset, _) = (*parameters).clone();
228
229 let query = Query::builder()
230 .limit(limit as u32)
231 .offset(offset as u32)
232 .build();
234
235 if let Some(client) = edc_connector_context.get_client() {
236 client
237 .common_expression_language(EdcConnectorApiVersion::V5Beta)
238 .query(query)
239 .await
240 .map_err(|error| {
241 log::error!("Error: {}", error);
242 error
243 })
244 .unwrap_or_default()
245 .into_iter()
246 .map(CommonExpressionLanguageItem::from)
247 .collect::<Vec<_>>()
248 } else {
249 vec![]
250 }
251 },
252 )?;
253
254 let common_expression_language_items = (*common_expression_language_items).clone();
255
256 Ok(html!(
257 <ListCommonExpressionLanguage
258 common_expression_language_items={common_expression_language_items}
259 offset={props.offset}
260 limit={props.limit}
261 onoffset={props.onoffset.clone()}
262 onlimit={props.onlimit.clone()}
263 ondelete={props.ondelete.clone()}
264 />
265 ))
266}