Skip to main content

edc_web_components/pages/
policy_page.rs

1use crate::components::ListPolicies;
2use crate::contexts::use_edc_connector_context;
3use crate::models::PolicyDefinitionItem;
4use edc_connector_client::EdcConnectorApiVersion;
5use edc_connector_client::types::query::Query;
6use patternfly_yew::prelude::*;
7use yew::platform::spawn_local;
8use yew::prelude::*;
9use yew::suspense::use_future_with;
10
11#[derive(Clone, Debug, PartialEq, Properties)]
12pub struct PolicyPageProps {
13  #[prop_or("List Policies".to_string())]
14  pub title: String,
15  #[prop_or(Some("A policy consists of one or more rules. The policy is then bound to an asset during the creation of the contract definition.".to_string()))]
16  pub tag_line: Option<String>,
17  #[prop_or("Create a Policy".to_string())]
18  pub create_title: String,
19  pub on_new_policy: Callback<()>,
20  pub onshow: Callback<String>,
21}
22
23#[component]
24pub fn PolicyPage(props: &PolicyPageProps) -> Html {
25  let refresh = use_state(|| 0usize);
26  let offset = use_state(|| 0usize);
27  let limit = use_state(|| 10usize);
28
29  let onoffset = use_callback(
30    (refresh.clone(), offset.setter()),
31    |offset, (refresh, offset_setter)| {
32      offset_setter.set(offset);
33      refresh.set(**refresh + 1);
34    },
35  );
36
37  let onlimit = use_callback(
38    (refresh.clone(), limit.setter()),
39    |limit, (refresh, limit_setter)| {
40      limit_setter.set(limit);
41      refresh.set(**refresh + 1);
42    },
43  );
44
45  let edc_connector_context = use_edc_connector_context();
46
47  let ondelete = use_callback(
48    (refresh.clone(), edc_connector_context),
49    |policy_id: String, (refresh, edc_connector_context)| {
50      let refresh = refresh.clone();
51      let edc_connector_context = edc_connector_context.clone();
52      let policy_id = policy_id.clone();
53
54      spawn_local(async move {
55        if let Some(client) = edc_connector_context.get_client() {
56          let _ = client
57            .policies(EdcConnectorApiVersion::V4)
58            .delete(&policy_id)
59            .await;
60          log::warn!("Deleted policy {} - {}", policy_id, *refresh + 1);
61          refresh.set(*refresh + 1);
62        }
63      });
64    },
65  );
66
67  let onclick = use_callback(props.on_new_policy.clone(), |_, on_new_policy| {
68    on_new_policy.emit(());
69  });
70
71  let tag_line = props
72    .tag_line
73    .as_ref()
74    .map(|tag_line| html!(<p>{ tag_line }</p>))
75    .unwrap_or_default();
76
77  html!(
78    <Stack gutter=true>
79      <StackItem>
80        <Split gutter=true>
81          <SplitItem fill=true>
82            <Title level={Level::H3} size={Size::XXLarge}>{ &props.title }</Title>
83            { tag_line }
84          </SplitItem>
85          <SplitItem>
86            <Button icon={Icon::Plus} {onclick} variant={ButtonVariant::Primary}>
87              { &props.create_title }
88            </Button>
89          </SplitItem>
90        </Split>
91      </StackItem>
92      <StackItem>
93        <Suspense>
94          <PolicyPageInner
95            offset={*offset}
96            limit={*limit}
97            {onoffset}
98            {onlimit}
99            {ondelete}
100            onshow={props.onshow.clone()}
101            force_refresh={*refresh}
102          />
103        </Suspense>
104      </StackItem>
105    </Stack>
106  )
107}
108
109#[derive(Clone, Debug, PartialEq, Properties)]
110pub struct PolicyPageInnerProps {
111  pub offset: usize,
112  pub limit: usize,
113  pub onoffset: Callback<usize>,
114  pub onlimit: Callback<usize>,
115  pub ondelete: Callback<String>,
116  pub onshow: Callback<String>,
117  pub force_refresh: usize,
118}
119
120#[component]
121pub fn PolicyPageInner(props: &PolicyPageInnerProps) -> HtmlResult {
122  let edc_connector_context = use_edc_connector_context();
123
124  let policy_definition_items = use_future_with(
125    (
126      edc_connector_context,
127      props.limit,
128      props.offset,
129      props.force_refresh,
130    ),
131    |parameters| async move {
132      let (edc_connector_context, limit, offset, _) = (*parameters).clone();
133
134      let query = Query::builder()
135        .limit(limit as u32)
136        .offset(offset as u32)
137        .build();
138
139      if let Some(client) = edc_connector_context.get_client() {
140        client
141          .policies(EdcConnectorApiVersion::V4)
142          .query(query)
143          .await
144          .unwrap_or_default()
145          .into_iter()
146          .map(PolicyDefinitionItem::from)
147          .collect::<Vec<_>>()
148      } else {
149        vec![]
150      }
151    },
152  )?;
153
154  let policy_definition_items = (*policy_definition_items).clone();
155
156  Ok(html!(
157    <ListPolicies
158      policy_definition_items={policy_definition_items}
159      offset={props.offset}
160      limit={props.limit}
161      onoffset={props.onoffset.clone()}
162      onlimit={props.onlimit.clone()}
163      ondelete={props.ondelete.clone()}
164      onshow={props.onshow.clone()}
165    />
166  ))
167}