edc_web_components/pages/
federated_catalog_management_page.rs1use 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}