edc_web_components/components/
policy_selector.rs1use crate::contexts::use_edc_connector_context;
2use crate::models::PolicyDefinitionItem;
3use edc_connector_client::EdcConnectorApiVersion;
4use edc_connector_client::types::query::Query;
5use patternfly_yew::prelude::*;
6use yew::prelude::*;
7use yew::suspense::use_future_with;
8
9#[derive(Clone, Debug, PartialEq, Properties)]
10pub struct PolicySelectorProps {
11 pub selected_policy: Option<PolicyDefinitionItem>,
12 pub onselect: Callback<PolicyDefinitionItem>,
13 #[prop_or("selectable-policy".to_string())]
14 pub select_id: String,
15}
16
17#[component]
18pub fn PolicySelector(props: &PolicySelectorProps) -> Html {
19 html!(
20 <Suspense>
21 <PolicySelectorInner
22 onselect={props.onselect.clone()}
23 selected_policy={props.selected_policy.clone()}
24 select_id={props.select_id.clone()}
25 />
26 </Suspense>
27 )
28}
29
30#[derive(Clone, Debug, PartialEq, Properties)]
31pub struct PolicySelectorInnerProps {
32 pub selected_policy: Option<PolicyDefinitionItem>,
33 pub onselect: Callback<PolicyDefinitionItem>,
34 pub select_id: String,
35}
36
37#[component]
38fn PolicySelectorInner(props: &PolicySelectorInnerProps) -> HtmlResult {
39 let limit = use_state(|| 10usize);
40 let offset = use_state(|| 0usize);
41 let force_refresh = use_state(|| 0usize);
42 let edc_connector_context = use_edc_connector_context();
43
44 let policies = use_future_with(
45 (edc_connector_context, *limit, *offset, *force_refresh),
46 |parameters| async move {
47 let (edc_connector_context, limit, offset, _) = (*parameters).clone();
48
49 let query = Query::builder()
50 .limit(limit as u32)
51 .offset(offset as u32)
52 .build();
53
54 if let Some(client) = edc_connector_context.get_client() {
55 client
56 .policies(EdcConnectorApiVersion::V4)
57 .query(query)
58 .await
59 .unwrap_or_default()
60 .into_iter()
61 .map(PolicyDefinitionItem::from)
62 .collect::<Vec<_>>()
63 } else {
64 vec![]
65 }
66 },
67 )?;
68
69 let policies = (*policies).clone();
70
71 let items = policies.iter().map(|policy_definition_item| {
72 let policy_definition_item_id = policy_definition_item.id.to_string();
73 let onselect = props.onselect.clone();
74
75 let selectable_actions = {
76 let policy_definition_item = policy_definition_item.clone();
77
78 yew::props!(CardSelectableActionsObjectProperties {
79 action: CardSelectableActionsVariant::Click {
80 onclick: Some(onselect.reform(move |_| policy_definition_item.clone()))
81 },
82 base: yew::props!(CardSelectableActionsObjectBase {
83 name: props.select_id.clone(),
84 })
85 })
86 };
87
88 html!(
89 <Card
90 selectable=true
91 selected={Some(policy_definition_item) == props.selected_policy.as_ref()}
92 >
93 <CardHeader {selectable_actions}>{ policy_definition_item_id }</CardHeader>
94 </Card>
95 )
96 });
97
98 let onlimit = use_callback(limit.setter(), |limit, limit_setter| {
99 limit_setter.set(limit)
100 });
101
102 let total_entries = Option::<usize>::None;
103
104 let nav_callback = use_callback(
105 (offset.clone(), *limit, total_entries),
106 |page: Navigation, (offset, limit, total_entries)| {
107 let new_offset = match page {
108 Navigation::First => 0,
109 Navigation::Last => (total_entries.unwrap_or_default().saturating_sub(1) / limit) * limit,
110 Navigation::Previous => **offset - limit,
111 Navigation::Next => **offset + limit,
112 Navigation::Page(n) => n * limit,
113 };
114 offset.set(new_offset);
115 },
116 );
117
118 Ok(html!(
119 <Stack gutter=true>
120 <StackItem>
121 <Pagination
122 offset={*offset}
123 entries_per_page_choices={vec![5, 10, 25, 50, 100]}
124 selected_choice={*limit}
125 onlimit={&onlimit}
126 onnavigation={&nav_callback}
127 />
128 </StackItem>
129 <StackItem>
130 <Gallery gutter=true>{ for items }</Gallery>
131 </StackItem>
132 </Stack>
133 ))
134}