edc-web-ui 0.2.0

A Rust Web interface with patternfly-yew client for EDC
Documentation
use crate::components::PolicySelector;
use crate::components::criterion_edit::CriterionEdit;
use crate::contexts::use_edc_connector_context;
use crate::models::PolicyDefinitionItem;
use edc_connector_client::types::contract_definition::NewContractDefinition;
use edc_connector_client::types::query::Criterion;
use patternfly_yew::prelude::*;
use yew::platform::spawn_local;
use yew::prelude::*;

#[derive(Clone, Debug, PartialEq, Properties)]
pub struct CreateContractDefinitionProps {
  #[prop_or_default]
  pub on_create: Callback<()>,
}

#[component]
pub fn CreateContractDefinition(props: &CreateContractDefinitionProps) -> Html {
  let edc_connector_context = use_edc_connector_context();

  let identifier = use_state(|| "".to_string());
  let access_policy_definition_item = use_state(|| Option::<PolicyDefinitionItem>::None);
  let contract_policy_definition_item = use_state(|| Option::<PolicyDefinitionItem>::None);
  let asset_selector = use_state(|| (String::new(), String::new(), String::new()));

  let onsubmit = use_callback(
    (
      edc_connector_context.clone(),
      identifier.clone(),
      access_policy_definition_item.clone(),
      contract_policy_definition_item.clone(),
      asset_selector.clone(),
      props.on_create.clone(),
    ),
    |event: SubmitEvent,
     (
      edc_connector_context,
      identifier,
      access_policy_definition_item,
      contract_policy_definition_item,
      asset_selector,
      on_create,
    )| {
      event.prevent_default();

      let edc_connector_context = edc_connector_context.clone();
      let identifier = (**identifier).clone();
      let access_policy_definition_item = (**access_policy_definition_item).clone();
      let contract_policy_definition_item = (**contract_policy_definition_item).clone();
      let asset_selector = (**asset_selector).clone();
      let on_create = on_create.clone();

      spawn_local(async move {
        let new_contract_definition = NewContractDefinition::builder()
          .id(&identifier)
          .access_policy_id(
            access_policy_definition_item
              .map(|policy_definition_item| policy_definition_item.id)
              .unwrap_or_default(),
          )
          .contract_policy_id(
            contract_policy_definition_item
              .map(|policy_definition_item| policy_definition_item.id.to_string())
              .unwrap_or_default(),
          );

        let (left, operator, right) = asset_selector;
        let new_contract_definition =
          if !left.is_empty() && !operator.is_empty() && !right.is_empty() {
            new_contract_definition.asset_selector(Criterion::new(&left, &operator, &right))
          } else {
            new_contract_definition
          };

        let new_contract_definition = new_contract_definition.build();

        if let Some(client) = edc_connector_context.get_client() {
          let _ = client
            .contract_definitions()
            .create(&new_contract_definition)
            .await;

          on_create.emit(());
        }
      })
    },
  );

  let onchange_identifier =
    use_callback(identifier.setter(), move |identifier, identifier_setter| {
      identifier_setter.set(identifier);
    });

  let onselect_access_policy = use_callback(
    access_policy_definition_item.setter(),
    move |access_policy_definition_item, access_policy_definition_item_setter| {
      access_policy_definition_item_setter.set(Some(access_policy_definition_item));
    },
  );

  let onselect_contract_policy = use_callback(
    contract_policy_definition_item.setter(),
    move |contract_policy, contract_policy_setter| {
      contract_policy_setter.set(Some(contract_policy));
    },
  );

  let disabled = (*identifier).is_empty()
    || (*access_policy_definition_item).is_none()
    || (*contract_policy_definition_item).is_none();

  let (operand_left, operator, operand_right) = (*asset_selector).clone();

  let onchange_asset_selection = {
    let asset_selector = asset_selector.clone();

    use_callback((), move |value, _| {
      asset_selector.set(value);
    })
  };

  html!(
    <Form {onsubmit}>
      <FormGroup label="Identifier" required=true>
        <TextInput required=true value={(*identifier).to_string()} onchange={onchange_identifier} />
      </FormGroup>
      <FormGroup label="Access Policy" required=true>
        <PolicySelector
          onselect={onselect_access_policy}
          selected_policy={(*access_policy_definition_item).clone()}
          select_id="selectable-access-policy"
        />
      </FormGroup>
      <FormGroup label="Contract Policy" required=true>
        <PolicySelector
          onselect={onselect_contract_policy}
          selected_policy={(*contract_policy_definition_item).clone()}
          select_id="selectable-contract-policy"
        />
      </FormGroup>
      <FormGroup label="Asset Selector">
        <CriterionEdit
          {operand_left}
          {operator}
          {operand_right}
          onchange={onchange_asset_selection}
        />
      </FormGroup>
      <ActionGroup>
        <Button
          variant={ButtonVariant::Primary}
          label="Submit"
          r#type={ButtonType::Submit}
          {disabled}
        />
      </ActionGroup>
    </Form>
  )
}