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