edc-web-components 0.3.0

A Rust Web Components with patternfly-yew client for EDC
Documentation
use crate::components::{ListAssetsGallery, SelectedFederatedCatalogOffer};
use crate::models::{AssetItem, Creator, Thumbnail};
use edc_federated_catalog_client::{FederatedCatalogClient, FederatedCatalogClientVersion};
use patternfly_yew::prelude::*;
use yew::prelude::*;
use yew::suspense::use_future_with;
use yew_oauth2::hook::use_latest_access_token;

#[derive(Clone, Debug, PartialEq, Properties)]
pub struct CatalogPageProps {
  pub onselectedoffer: Callback<SelectedFederatedCatalogOffer>,
}

#[component]
pub fn CatalogPage(props: &CatalogPageProps) -> Html {
  let refresh = use_state(|| 0usize);

  html!(
    <Stack gutter=true>
      <StackItem>
        <Split gutter=true>
          <SplitItem fill=true>
            <Title level={Level::H3} size={Size::XXLarge}>{ "Catalog" }</Title>
          </SplitItem>
        </Split>
      </StackItem>
      <StackItem>
        <Suspense>
          <CatalogPageInner
            force_refresh={*refresh}
            onselectedoffer={props.onselectedoffer.clone()}
          />
        </Suspense>
      </StackItem>
    </Stack>
  )
}

#[derive(Clone, Debug, PartialEq, Properties)]
pub struct CatalogPageInnerProps {
  pub force_refresh: usize,
  pub onselectedoffer: Callback<SelectedFederatedCatalogOffer>,
}

#[component]
pub fn CatalogPageInner(props: &CatalogPageInnerProps) -> HtmlResult {
  let latest_access_token_context = use_latest_access_token().unwrap();

  let asset_items = use_future_with(
    (latest_access_token_context.clone(), props.force_refresh),
    |parameters| async move {
      let (latest_access_token_context, _) = (*parameters).clone();

      let server_url = web_sys::window().unwrap().location().origin().unwrap();
      let federated_catalog_client = FederatedCatalogClient::new(
        reqwest::Client::new(),
        format!("{server_url}/federated-catalog"),
        latest_access_token_context.access_token(),
        FederatedCatalogClientVersion::V4,
      );

      federated_catalog_client
        .list_offers()
        .await
        .unwrap_or_default()
        .iter()
        .flat_map(|federated_catalog_offer| {
          federated_catalog_offer
            .dataset
            .clone()
            .into_iter()
            .map(|dataset| {
              let asset_item = AssetItem {
                id: dataset.id.clone(),
                name: dataset.name,
                version: dataset
                  .version
                  .and_then(|version| semver::Version::parse(&version).ok()),
                description: dataset.description,
                creator: dataset.creator.map(|creator| Creator {
                  name: Some(creator.name),
                  thumbnail: Some(Thumbnail {
                    resource: Some(creator.thumbnail.resource),
                  }),
                }),
                thumbnail: dataset.thumbnail.map(|thumbnail| Thumbnail {
                  resource: Some(thumbnail.resource),
                }),
                keywords: dataset.keywords,
                base_url: "".to_string(),
                proxy_path: false,
                proxy_query_params: false,
                proxy_method: false,
                proxy_body: false,
              };

              let selected_offer = SelectedFederatedCatalogOffer {
                originator: federated_catalog_offer.originator.clone(),
                provider_id: federated_catalog_offer.participant_id.id.clone(),
                dataset_id: dataset.id.clone(),
              };

              (asset_item, selected_offer)
            })
            .collect::<Vec<_>>()
        })
        .unzip()
    },
  )?;

  let (asset_items, selected_offers): (Vec<AssetItem>, Vec<SelectedFederatedCatalogOffer>) =
    (*asset_items).clone();

  let onshow = use_callback(
    (props.onselectedoffer.clone(), selected_offers),
    |dataset_id, (onselectedoffer, selected_offers)| {
      if let Some(selected_offer) = selected_offers
        .iter()
        .find(|selected_offer| selected_offer.dataset_id == dataset_id)
      {
        onselectedoffer.emit(selected_offer.clone());
      }
    },
  );

  Ok(html!(<ListAssetsGallery {asset_items} {onshow} />))
}