Skip to main content

edc_web_components/pages/
common_expression_language_page.rs

1use 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        // .filter("https://w3id.org/edc/v0.0.1/ns/master-catalog-company-id", "=", "424F9F7A-BBC8-4BAD-B128-C3D0A693ABBA")
229        .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}