Skip to main content

edc_web_components/pages/
contract_definition_page.rs

1use crate::components::ListContractDefinitions;
2use crate::contexts::use_edc_connector_context;
3use crate::models::ContractDefinitionItem;
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 ContractDefinitionPageProps {
13  pub on_new_contract_definition: Callback<()>,
14  #[prop_or_default]
15  pub on_policy_click: Callback<String>,
16  #[prop_or_default]
17  pub on_asset_click: Callback<String>,
18}
19
20#[component]
21pub fn ContractDefinitionPage(props: &ContractDefinitionPageProps) -> Html {
22  let refresh = use_state(|| 0usize);
23  let offset = use_state(|| 0usize);
24  let limit = use_state(|| 10usize);
25
26  let onoffset = use_callback(
27    (refresh.clone(), offset.setter()),
28    |offset, (refresh, offset_setter)| {
29      offset_setter.set(offset);
30      refresh.set(**refresh + 1);
31    },
32  );
33
34  let onlimit = use_callback(
35    (refresh.clone(), limit.setter()),
36    |limit, (refresh, limit_setter)| {
37      limit_setter.set(limit);
38      refresh.set(**refresh + 1);
39    },
40  );
41
42  let edc_connector_context = use_edc_connector_context();
43
44  let ondelete = use_callback(
45    (refresh.clone(), edc_connector_context),
46    |contract_definition_id: String, (refresh, edc_connector_context)| {
47      let refresh = refresh.clone();
48      let edc_connector_context = edc_connector_context.clone();
49      let contract_definition_id = contract_definition_id.clone();
50
51      spawn_local(async move {
52        if let Some(client) = edc_connector_context.get_client() {
53          let _ = client
54            .contract_definitions(EdcConnectorApiVersion::V4)
55            .delete(&contract_definition_id)
56            .await;
57        }
58        refresh.set(*refresh + 1);
59      });
60    },
61  );
62
63  let onclick = use_callback(
64    props.on_new_contract_definition.clone(),
65    |_, on_new_contract_definition| {
66      on_new_contract_definition.emit(());
67    },
68  );
69
70  html!(
71    <Stack gutter=true>
72      <StackItem>
73        <Split gutter=true>
74          <SplitItem fill=true>
75            <Title level={Level::H3} size={Size::XXLarge}>{ "List Contract Definitions" }</Title>
76            <p>
77              { "A contract definition links an asset to an access policy and a contract policy. The contract definition constitutes an offer to the other participants." }
78            </p>
79          </SplitItem>
80          <SplitItem>
81            <Button icon={Icon::Plus} {onclick} variant={ButtonVariant::Primary}>
82              { "Create a Contract Definition" }
83            </Button>
84          </SplitItem>
85        </Split>
86      </StackItem>
87      <StackItem>
88        <Suspense>
89          <ContractDefinitionPageInner
90            offset={*offset}
91            limit={*limit}
92            {onoffset}
93            {onlimit}
94            {ondelete}
95            on_policy_click={props.on_policy_click.clone()}
96            on_asset_click={props.on_asset_click.clone()}
97            force_refresh={*refresh}
98          />
99        </Suspense>
100      </StackItem>
101    </Stack>
102  )
103}
104
105#[derive(Clone, Debug, PartialEq, Properties)]
106pub struct ContractDefinitionPageInnerProps {
107  pub offset: usize,
108  pub limit: usize,
109  pub onoffset: Callback<usize>,
110  pub onlimit: Callback<usize>,
111  pub ondelete: Callback<String>,
112  #[prop_or_default]
113  pub on_policy_click: Callback<String>,
114  #[prop_or_default]
115  pub on_asset_click: Callback<String>,
116  pub force_refresh: usize,
117}
118
119#[component]
120pub fn ContractDefinitionPageInner(props: &ContractDefinitionPageInnerProps) -> HtmlResult {
121  let edc_connector_context = use_edc_connector_context();
122
123  let contract_definition_items = use_future_with(
124    (
125      edc_connector_context,
126      props.limit,
127      props.offset,
128      props.force_refresh,
129    ),
130    |parameters| async move {
131      let (edc_connector_context, limit, offset, _) = (*parameters).clone();
132
133      let query = Query::builder()
134        .limit(limit as u32)
135        .offset(offset as u32)
136        .build();
137
138      if let Some(client) = edc_connector_context.get_client() {
139        client
140          .contract_definitions(EdcConnectorApiVersion::V4)
141          .query(query)
142          .await
143          .unwrap_or_default()
144          .into_iter()
145          .map(ContractDefinitionItem::from)
146          .collect()
147      } else {
148        vec![]
149      }
150    },
151  )?;
152
153  let contract_definition_items = (*contract_definition_items).clone();
154
155  Ok(html!(
156    <ListContractDefinitions
157      contract_definition_items={contract_definition_items}
158      offset={props.offset}
159      limit={props.limit}
160      onoffset={props.onoffset.clone()}
161      onlimit={props.onlimit.clone()}
162      ondelete={props.ondelete.clone()}
163      on_policy_click={props.on_policy_click.clone()}
164      on_asset_click={props.on_asset_click.clone()}
165    />
166  ))
167}