Skip to main content

edc_web_components/pages/
federated_catalog_page.rs

1use crate::components::{ListAssetsGallery, SelectedFederatedCatalogOffer};
2use crate::models::{AssetItem, Creator, Thumbnail};
3use edc_federated_catalog_client::{FederatedCatalogClient, FederatedCatalogClientVersion};
4use patternfly_yew::prelude::*;
5use yew::prelude::*;
6use yew::suspense::use_future_with;
7use yew_oauth2::hook::use_latest_access_token;
8
9#[derive(Clone, Debug, PartialEq, Properties)]
10pub struct CatalogPageProps {
11  pub onselectedoffer: Callback<SelectedFederatedCatalogOffer>,
12}
13
14#[component]
15pub fn CatalogPage(props: &CatalogPageProps) -> Html {
16  let refresh = use_state(|| 0usize);
17
18  html!(
19    <Stack gutter=true>
20      <StackItem>
21        <Split gutter=true>
22          <SplitItem fill=true>
23            <Title level={Level::H3} size={Size::XXLarge}>{ "Catalog" }</Title>
24          </SplitItem>
25        </Split>
26      </StackItem>
27      <StackItem>
28        <Suspense>
29          <CatalogPageInner
30            force_refresh={*refresh}
31            onselectedoffer={props.onselectedoffer.clone()}
32          />
33        </Suspense>
34      </StackItem>
35    </Stack>
36  )
37}
38
39#[derive(Clone, Debug, PartialEq, Properties)]
40pub struct CatalogPageInnerProps {
41  pub force_refresh: usize,
42  pub onselectedoffer: Callback<SelectedFederatedCatalogOffer>,
43}
44
45#[component]
46pub fn CatalogPageInner(props: &CatalogPageInnerProps) -> HtmlResult {
47  let latest_access_token_context = use_latest_access_token().unwrap();
48
49  let asset_items = use_future_with(
50    (latest_access_token_context.clone(), props.force_refresh),
51    |parameters| async move {
52      let (latest_access_token_context, _) = (*parameters).clone();
53
54      let server_url = web_sys::window().unwrap().location().origin().unwrap();
55      let federated_catalog_client = FederatedCatalogClient::new(
56        reqwest::Client::new(),
57        format!("{server_url}/federated-catalog"),
58        latest_access_token_context.access_token(),
59        FederatedCatalogClientVersion::V4,
60      );
61
62      federated_catalog_client
63        .list_offers()
64        .await
65        .unwrap_or_default()
66        .iter()
67        .flat_map(|federated_catalog_offer| {
68          federated_catalog_offer
69            .dataset
70            .clone()
71            .into_iter()
72            .map(|dataset| {
73              let asset_item = AssetItem {
74                id: dataset.id.clone(),
75                name: dataset.name,
76                version: dataset
77                  .version
78                  .and_then(|version| semver::Version::parse(&version).ok()),
79                description: dataset.description,
80                creator: dataset.creator.map(|creator| Creator {
81                  name: Some(creator.name),
82                  thumbnail: Some(Thumbnail {
83                    resource: Some(creator.thumbnail.resource),
84                  }),
85                }),
86                thumbnail: dataset.thumbnail.map(|thumbnail| Thumbnail {
87                  resource: Some(thumbnail.resource),
88                }),
89                keywords: dataset.keywords,
90                base_url: "".to_string(),
91                proxy_path: false,
92                proxy_query_params: false,
93                proxy_method: false,
94                proxy_body: false,
95              };
96
97              let selected_offer = SelectedFederatedCatalogOffer {
98                originator: federated_catalog_offer.originator.clone(),
99                provider_id: federated_catalog_offer.participant_id.id.clone(),
100                dataset_id: dataset.id.clone(),
101              };
102
103              (asset_item, selected_offer)
104            })
105            .collect::<Vec<_>>()
106        })
107        .unzip()
108    },
109  )?;
110
111  let (asset_items, selected_offers): (Vec<AssetItem>, Vec<SelectedFederatedCatalogOffer>) =
112    (*asset_items).clone();
113
114  let onshow = use_callback(
115    (props.onselectedoffer.clone(), selected_offers),
116    |dataset_id, (onselectedoffer, selected_offers)| {
117      if let Some(selected_offer) = selected_offers
118        .iter()
119        .find(|selected_offer| selected_offer.dataset_id == dataset_id)
120      {
121        onselectedoffer.emit(selected_offer.clone());
122      }
123    },
124  );
125
126  Ok(html!(<ListAssetsGallery {asset_items} {onshow} />))
127}