edc_web_components/contexts/
edc_federated_catalog_assets_context.rs1use crate::components::SelectedFederatedCatalogOffer;
2use crate::models::AssetItem;
3use edc_federated_catalog_client::{FederatedCatalogClient, FederatedCatalogClientVersion};
4use std::{ops::Deref, rc::Rc};
5use yew::prelude::*;
6use yew::suspense::use_future_with;
7use yew_oauth2::hook::use_latest_access_token;
8
9#[derive(Debug, PartialEq, Clone)]
10pub enum EdcFederatedCatalogAssetsAction {
11 SetAssetsAndSelectedOffers(Vec<(AssetItem, SelectedFederatedCatalogOffer)>),
12}
13
14#[derive(Clone, PartialEq)]
15pub struct EdcFederatedCatalogAssetsContextState {
16 asset_items: Vec<AssetItem>,
17 selected_offers: Vec<SelectedFederatedCatalogOffer>,
18}
19
20impl EdcFederatedCatalogAssetsContextState {
21 pub fn asset(&self, asset_id: &str) -> Option<&AssetItem> {
22 self
23 .asset_items
24 .iter()
25 .find(|asset_item| asset_item.id == asset_id)
26 }
27
28 pub fn asset_items(&self) -> &[AssetItem] {
29 &self.asset_items
30 }
31
32 pub fn selected_offers(&self) -> &[SelectedFederatedCatalogOffer] {
33 &self.selected_offers
34 }
35}
36
37impl Reducible for EdcFederatedCatalogAssetsContextState {
38 type Action = EdcFederatedCatalogAssetsAction;
39
40 fn reduce(self: Rc<Self>, action: Self::Action) -> Rc<Self> {
41 let mut new_self = self.deref().clone();
42
43 let EdcFederatedCatalogAssetsAction::SetAssetsAndSelectedOffers(assets_and_selected_offers) =
44 action;
45
46 let (assets, selected_offers) = assets_and_selected_offers.into_iter().unzip();
47
48 new_self.asset_items = assets;
49 new_self.selected_offers = selected_offers;
50
51 new_self.into()
52 }
53}
54
55#[derive(Properties, PartialEq)]
56pub struct EdcFederatedCatalogAssetsContextProviderProps {
57 #[prop_or_default]
58 pub children: Html,
59}
60
61#[component]
62pub fn EdcFederatedCatalogAssetsContextProvider(
63 props: &EdcFederatedCatalogAssetsContextProviderProps,
64) -> Html {
65 let did_resolver_context = use_reducer(move || EdcFederatedCatalogAssetsContextState {
66 asset_items: vec![],
67 selected_offers: vec![],
68 });
69
70 html! {
71 <ContextProvider<EdcFederatedCatalogAssetsContext> context={did_resolver_context}>
72 { props.children.clone() }
73 </ContextProvider<EdcFederatedCatalogAssetsContext >>
74 }
75}
76
77pub type EdcFederatedCatalogAssetsContext = UseReducerHandle<EdcFederatedCatalogAssetsContextState>;
78
79#[hook]
80pub fn use_edc_federated_catalog_assets_context() -> Option<EdcFederatedCatalogAssetsContext> {
81 use_context::<EdcFederatedCatalogAssetsContext>()
82}
83
84#[derive(Properties, PartialEq)]
85pub struct EdcFederatedCatalogAssetsFetcherProps {
86 #[prop_or("/federated-catalog".to_string())]
87 pub federated_catalog_endpoint: String,
88 #[prop_or_default]
89 pub search: Option<String>,
90 #[prop_or_default]
91 pub dcterm_types: Vec<String>,
92 #[prop_or_default]
93 pub force_refresh: usize,
94}
95
96#[component]
97pub fn EdcFederatedCatalogAssetsFetcher(
98 props: &EdcFederatedCatalogAssetsFetcherProps,
99) -> HtmlResult {
100 let latest_access_token_context = use_latest_access_token().unwrap();
101 let edc_federated_catalog_assets_context = use_edc_federated_catalog_assets_context();
102
103 let _ = use_future_with(
104 (
105 props.force_refresh,
106 props.federated_catalog_endpoint.clone(),
107 props.search.clone(),
108 props.dcterm_types.clone(),
109 latest_access_token_context.clone(),
110 edc_federated_catalog_assets_context.clone(),
111 ),
112 |parameters| async move {
113 let (
114 _,
115 federated_catalog_endpoint,
116 search,
117 dcterm_types,
118 latest_access_token_context,
119 edc_federated_catalog_assets_context,
120 ) = (*parameters).clone();
121
122 if let Some(edc_federated_catalog_assets_context) = edc_federated_catalog_assets_context {
123 let server_url = web_sys::window().unwrap().location().origin().unwrap();
124 let federated_catalog_client = FederatedCatalogClient::new(
125 reqwest::Client::new(),
126 format!("{server_url}{}", federated_catalog_endpoint),
127 latest_access_token_context.access_token(),
128 FederatedCatalogClientVersion::V4,
129 );
130
131 let assets_and_selected_offers = federated_catalog_client
132 .list_offers()
133 .await
134 .unwrap_or_default()
135 .iter()
136 .flat_map(|federated_catalog_offer| {
137 federated_catalog_offer
138 .dataset
139 .clone()
140 .into_iter()
141 .map(|dataset| {
142 let dataset_id = dataset.id.clone();
143 let asset_item = AssetItem::from(dataset);
144
145 let selected_offer = SelectedFederatedCatalogOffer {
146 originator: federated_catalog_offer.originator.clone(),
147 provider_id: federated_catalog_offer.participant_id.id.clone(),
148 dataset_id,
149 };
150
151 (asset_item, selected_offer)
152 })
153 .filter(|(asset_item, _)| asset_item.is_filtered(&search, &dcterm_types))
154 .collect::<Vec<_>>()
155 })
156 .collect::<Vec<_>>();
157
158 edc_federated_catalog_assets_context.dispatch(
159 EdcFederatedCatalogAssetsAction::SetAssetsAndSelectedOffers(assets_and_selected_offers),
160 );
161 }
162 },
163 )?;
164
165 Ok(html!())
166}