edc-web-ui 0.1.0

A Rust Web interface with patternfly-yew client for EDC
Documentation
use crate::contexts::use_edc_connector_context;
use edc_connector_client::types::contract_negotiation::ContractRequest;
use edc_connector_client::types::policy::Policy;
use edc_connector_client::types::query::Query;
use patternfly_yew::prelude::*;
use std::fmt::{Display, Formatter};
use yew::platform::spawn_local;
use yew::prelude::*;
use yew::suspense::use_future;

#[function_component]
pub fn CreateContractNegotiation() -> Html {
  html!(
    <Suspense>
      <CreateContractNegotiationInner />
    </Suspense>
  )
}

#[function_component]
pub fn CreateContractNegotiationInner() -> HtmlResult {
  let edc_connector_context = use_edc_connector_context();

  let counter_party_address = use_state(|| "".to_string());
  let counter_party_id = use_state(|| "".to_string());
  let policy = use_state(|| None);

  let policies = {
    let edc_connector_context = edc_connector_context.clone();

    use_future(|| async move {
      if let Some(client) = edc_connector_context.get_client() {
        let query = Query::default();
        let policies = client.policies().query(query).await.unwrap_or_default();

        policies
          .iter()
          .map(|policy| PolicySelector(policy.id().to_string(), policy.policy().clone()))
          .collect::<Vec<_>>()
      } else {
        vec![]
      }
    })?
  };

  let onsubmit = use_callback(
    (
      edc_connector_context.clone(),
      counter_party_address.clone(),
      counter_party_id.clone(),
      policy.clone(),
    ),
    |event: SubmitEvent,
     (edc_connector_context, counter_party_address, counter_party_id, policy)| {
      event.prevent_default();

      let edc_connector_context = edc_connector_context.clone();
      let counter_party_address = (**counter_party_address).clone();
      let counter_party_id = (**counter_party_id).clone();
      let policy: Option<PolicySelector> = (**policy).clone();

      spawn_local(async move {
        if let Some(policy) = policy {
          let contract_request = ContractRequest::builder()
            .counter_party_address(counter_party_address)
            .counter_party_id(counter_party_id)
            .policy(policy.1)
            .build();

          if let Some(client) = edc_connector_context.get_client() {
            let _ = client
              .contract_negotiations()
              .initiate(&contract_request)
              .await;
          }
        }
      })
    },
  );

  let onchange_counter_party_address = {
    let counter_party_address = counter_party_address.clone();

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

  let onchange_counter_party_id = {
    let counter_party_id = counter_party_id.clone();

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

  let onselect_policy = {
    let policy = policy.clone();

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

  let disabled = (*policy).is_none();

  Ok(html!(
    <Form {onsubmit}>
      <FormGroup
        label={"Counter Party Address"}
        required={true}
        >
        <TextInput
          required={true}
          value={(*counter_party_address).to_string()}
          onchange={onchange_counter_party_address}
          />
      </FormGroup>

      <FormGroup
        label={"Counter Party ID"}
        required={true}
        >
        <TextInput
          required={true}
          value={(*counter_party_id).to_string()}
          onchange={onchange_counter_party_id}
          />
      </FormGroup>

      <FormGroup
        label={"Policy"}
        required={true}
        >
        <SimpleSelect<PolicySelector>
          selected={(*policy).clone()}
          onselect={onselect_policy}
          entries={(*policies).clone()}
          />
      </FormGroup>

      <ActionGroup>
        <Button
          variant={ButtonVariant::Primary}
          label="Submit"
          r#type={ButtonType::Submit}
          {disabled}
          />
        <Button variant={ButtonVariant::Secondary} label="Reset" r#type={ButtonType::Reset}/>
      </ActionGroup>
    </Form>
  ))
}

#[derive(Clone, PartialEq)]
struct PolicySelector(String, Policy);

impl Eq for PolicySelector {}

impl Display for PolicySelector {
  fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
    f.write_str(&self.0.clone())
  }
}