Skip to main content

edc_web_components/pages/
federated_catalog_management_page.rs

1use crate::components::{CreateFederatedCatalogParticipant, ListFederatedCatalogParticipants};
2use edc_federated_catalog_client::models::FederatedCatalogParticipant;
3use edc_federated_catalog_client::{FederatedCatalogClient, FederatedCatalogClientVersion};
4use patternfly_yew::prelude::*;
5use yew::platform::spawn_local;
6use yew::prelude::*;
7use yew::suspense::use_future_with;
8use yew_oauth2::hook::use_latest_access_token;
9
10#[derive(Clone, Debug, PartialEq, Properties)]
11pub struct ListFederatedCatalogParticipantsProps {
12  #[prop_or_default]
13  pub on_show_offer: Option<Callback<FederatedCatalogParticipant>>,
14  #[prop_or("Federated Catalog Participants".to_string())]
15  pub title: String,
16  #[prop_or(Some("Manage your followed participants, discover their latest data catalogs, and control your active catalog subscriptions.".to_string()))]
17  pub tag_line: Option<String>,
18}
19
20#[component]
21pub fn FederatedCatalogManagementPage(props: &ListFederatedCatalogParticipantsProps) -> Html {
22  let refresh = use_state(|| 0usize);
23  let backdropper = use_backdrop();
24
25  let on_create = use_callback(
26    (backdropper.clone(), refresh.clone()),
27    |_, (backdropper, refresh)| {
28      if let Some(backdropper) = backdropper {
29        backdropper.close();
30      }
31
32      refresh.set(**refresh + 1);
33    },
34  );
35
36  let onclick = use_callback((backdropper, on_create), |_, (backdropper, on_create)| {
37    if let Some(backdropper) = backdropper {
38      backdropper.open(html!(
39        <Bullseye>
40          <Modal variant={ModalVariant::Medium} title="Subscribe to a Participant">
41            <CreateFederatedCatalogParticipant {on_create} />
42          </Modal>
43        </Bullseye>
44      ))
45    }
46  });
47
48  let refresh_asked = use_callback(refresh.clone(), |_, refresh| {
49    refresh.set(**refresh + 1);
50  });
51
52  let tag_line = props
53    .tag_line
54    .as_ref()
55    .map(|tag_line| html!(<p>{ tag_line }</p>))
56    .unwrap_or_default();
57
58  html!(
59    <Stack gutter=true>
60      <StackItem>
61        <Split gutter=true>
62          <SplitItem fill=true>
63            <Title level={Level::H3} size={Size::XXLarge}>{ &props.title }</Title>
64            { tag_line }
65          </SplitItem>
66          <SplitItem>
67            <Button icon={Icon::Plus} {onclick} variant={ButtonVariant::Primary}>{ "Add" }</Button>
68          </SplitItem>
69        </Split>
70      </StackItem>
71      <StackItem>
72        <Suspense>
73          <ListFederatedCatalogParticipantsInner
74            force_refresh={*refresh}
75            {refresh_asked}
76            on_show_offer={props.on_show_offer.clone()}
77          />
78        </Suspense>
79      </StackItem>
80    </Stack>
81  )
82}
83
84#[derive(Clone, Debug, PartialEq, Properties)]
85pub struct ListFederatedCatalogParticipantsInnerProps {
86  force_refresh: usize,
87  refresh_asked: Callback<()>,
88  #[prop_or_default]
89  on_show_offer: Option<Callback<FederatedCatalogParticipant>>,
90}
91
92#[component]
93pub fn ListFederatedCatalogParticipantsInner(
94  props: &ListFederatedCatalogParticipantsInnerProps,
95) -> HtmlResult {
96  let latest_access_token_context = use_latest_access_token().unwrap();
97
98  let federated_catalog_participants = use_future_with(
99    (latest_access_token_context.clone(), props.force_refresh),
100    |parameters| async move {
101      let (latest_access_token_context, _) = (*parameters).clone();
102
103      let server_url = web_sys::window().unwrap().location().origin().unwrap();
104      let federated_catalog_client = FederatedCatalogClient::new(
105        reqwest::Client::new(),
106        format!("{server_url}/federated-catalog-management"),
107        latest_access_token_context.access_token(),
108        FederatedCatalogClientVersion::V4,
109      );
110
111      federated_catalog_client
112        .list_participants()
113        .await
114        .unwrap_or_default()
115    },
116  )?;
117
118  let federated_catalog_participants = (*federated_catalog_participants).clone();
119
120  let ondelete = use_callback(
121    (
122      latest_access_token_context.clone(),
123      props.refresh_asked.clone(),
124    ),
125    |federated_catalog_participant: FederatedCatalogParticipant,
126     (latest_access_token_context, refresh_asked)| {
127      let server_url = web_sys::window().unwrap().location().origin().unwrap();
128      let federated_catalog_client = FederatedCatalogClient::new(
129        reqwest::Client::new(),
130        format!("{server_url}/federated-catalog-management"),
131        latest_access_token_context.access_token(),
132        FederatedCatalogClientVersion::V4,
133      );
134      let refresh_asked = refresh_asked.clone();
135
136      spawn_local(async move {
137        if federated_catalog_client
138          .delete_participant(&federated_catalog_participant.id)
139          .await
140          .is_ok()
141        {
142          refresh_asked.emit(());
143        }
144      });
145    },
146  );
147
148  Ok(html!(
149    <ListFederatedCatalogParticipants
150      {federated_catalog_participants}
151      {ondelete}
152      on_show_offer={props.on_show_offer.clone()}
153    />
154  ))
155}