Skip to main content

edc_web_components/components/
create_contract_definition.rs

1use crate::components::{AssetSelector, PolicySelector};
2use crate::contexts::use_edc_connector_context;
3use crate::models::{AssetItem, PolicyDefinitionItem};
4use edc_connector_client::EdcConnectorApiVersion;
5use edc_connector_client::types::contract_definition::NewContractDefinition;
6use edc_connector_client::types::query::Criterion;
7use patternfly_yew::prelude::*;
8use uuid::Uuid;
9use yew::platform::spawn_local;
10use yew::prelude::*;
11
12#[derive(Clone, Debug, PartialEq, Properties)]
13pub struct CreateContractDefinitionProps {
14  #[prop_or_default]
15  pub on_create: Callback<()>,
16}
17
18#[component]
19pub fn CreateContractDefinition(props: &CreateContractDefinitionProps) -> Html {
20  let edc_connector_context = use_edc_connector_context();
21
22  let name = use_state(String::new);
23  let access_policy_definition_item = use_state(|| Option::<PolicyDefinitionItem>::None);
24  let contract_policy_definition_item = use_state(|| Option::<PolicyDefinitionItem>::None);
25  let asset_items = use_state(Vec::<AssetItem>::new);
26
27  let onsubmit = use_callback(
28    (
29      edc_connector_context.clone(),
30      name.clone(),
31      access_policy_definition_item.clone(),
32      contract_policy_definition_item.clone(),
33      asset_items.clone(),
34      props.on_create.clone(),
35    ),
36    |event: SubmitEvent,
37     (
38      edc_connector_context,
39      name,
40      access_policy_definition_item,
41      contract_policy_definition_item,
42      asset_items,
43      on_create,
44    )| {
45      event.prevent_default();
46
47      let edc_connector_context = edc_connector_context.clone();
48      let name = (**name).clone();
49      let access_policy_definition_item = (**access_policy_definition_item).clone();
50      let contract_policy_definition_item = (**contract_policy_definition_item).clone();
51      let asset_items = (**asset_items).clone();
52      let on_create = on_create.clone();
53
54      spawn_local(async move {
55        let mut new_contract_definition = NewContractDefinition::builder()
56          .id(Uuid::new_v4().to_string())
57          .private_property("name", name.clone())
58          .access_policy_id(
59            access_policy_definition_item
60              .map(|policy_definition_item| policy_definition_item.id)
61              .unwrap_or_default(),
62          )
63          .contract_policy_id(
64            contract_policy_definition_item
65              .map(|policy_definition_item| policy_definition_item.id.to_string())
66              .unwrap_or_default(),
67          );
68
69        if !asset_items.is_empty() {
70          new_contract_definition = new_contract_definition.asset_selector(Criterion::new(
71            "https://w3id.org/edc/v0.0.1/ns/id",
72            "IN",
73            asset_items
74              .iter()
75              .map(|asset_item| asset_item.id.clone())
76              .collect::<Vec<_>>(),
77          ));
78        }
79
80        let new_contract_definition = new_contract_definition.build();
81
82        if let Some(client) = edc_connector_context.get_client() {
83          let _ = client
84            .contract_definitions(EdcConnectorApiVersion::V4)
85            .create(&new_contract_definition)
86            .await;
87
88          on_create.emit(());
89        }
90      })
91    },
92  );
93
94  let onchange_name = use_callback(name.setter(), move |name, name_setter| {
95    name_setter.set(name);
96  });
97
98  let onselect_access_policy = use_callback(
99    access_policy_definition_item.setter(),
100    move |access_policy_definition_item, access_policy_definition_item_setter| {
101      access_policy_definition_item_setter.set(Some(access_policy_definition_item));
102    },
103  );
104
105  let onselect_contract_policy = use_callback(
106    contract_policy_definition_item.setter(),
107    move |contract_policy, contract_policy_setter| {
108      contract_policy_setter.set(Some(contract_policy));
109    },
110  );
111
112  let disabled = (*name).is_empty()
113    || (*access_policy_definition_item).is_none()
114    || (*contract_policy_definition_item).is_none();
115
116  let onselect_assets = use_callback(asset_items.setter(), |asset_items, asset_items_setter| {
117    asset_items_setter.set(asset_items);
118  });
119
120  html!(
121    <Form {onsubmit}>
122      <FormGroup label="Name" required=true>
123        <TextInput required=true value={(*name).to_string()} onchange={onchange_name} />
124      </FormGroup>
125      <FormGroup label="Asset Selector">
126        <HelperText>
127          <HelperTextItem>{ "Which asset is covered by this offer ?" }</HelperTextItem>
128        </HelperText>
129        <AssetSelector onselect={onselect_assets} selected_assets={(*asset_items).clone()} />
130      </FormGroup>
131      <FormGroup label="Access Policy" required=true>
132        <HelperText>
133          <HelperTextItem>{ "Who is eligible to view this offer ?" }</HelperTextItem>
134        </HelperText>
135        <PolicySelector
136          onselect={onselect_access_policy}
137          selected_policy={(*access_policy_definition_item).clone()}
138          select_id="selectable-access-policy"
139        />
140      </FormGroup>
141      <FormGroup label="Contract Policy" required=true>
142        <HelperText>
143          <HelperTextItem>{ "Who is eligible to negotiate this offer ?" }</HelperTextItem>
144        </HelperText>
145        <PolicySelector
146          onselect={onselect_contract_policy}
147          selected_policy={(*contract_policy_definition_item).clone()}
148          select_id="selectable-contract-policy"
149        />
150      </FormGroup>
151      <ActionGroup>
152        <Button
153          variant={ButtonVariant::Primary}
154          label="Submit"
155          r#type={ButtonType::Submit}
156          {disabled}
157        />
158      </ActionGroup>
159    </Form>
160  )
161}