edc_web_components/pages/
contract_negotiation_page.rs1use crate::components::ListContractNegotiations;
2use crate::contexts::use_edc_connector_context;
3use crate::models::ContractNegotiationItem;
4use edc_connector_client::EdcConnectorApiVersion;
5use edc_connector_client::types::query::Query;
6use patternfly_yew::prelude::*;
7use yew::prelude::*;
8use yew::suspense::use_future_with;
9
10#[derive(Clone, Debug, PartialEq, Properties)]
11pub struct ContractNegotiationPageProps {
12 pub on_show_contract_negotiation: Callback<String>,
13}
14
15#[component]
16pub fn ContractNegotiationPage(props: &ContractNegotiationPageProps) -> Html {
17 let refresh = use_state(|| 0usize);
18 let offset = use_state(|| 0usize);
19 let limit = use_state(|| 10usize);
20 let switch_view_consumer = use_state(|| false);
21 let statuses = use_state(|| {
22 vec![
23 ("Initial".to_string(), false),
24 ("Requesting".to_string(), false),
25 ("Requested".to_string(), false),
26 ("Offering".to_string(), false),
27 ("Offered".to_string(), false),
28 ("Accepting".to_string(), false),
29 ("Accepted".to_string(), false),
30 ("Agreeing".to_string(), false),
31 ("Agreed".to_string(), false),
32 ("Verifying".to_string(), false),
33 ("Verified".to_string(), false),
34 ("Finalizing".to_string(), false),
35 ("Finalized".to_string(), false),
36 ("Terminating".to_string(), false),
37 ("Terminated".to_string(), false),
38 ]
39 });
40
41 let on_offset = use_callback(
42 (refresh.clone(), offset.setter()),
43 |offset, (refresh, offset_setter)| {
44 offset_setter.set(offset);
45 refresh.set(**refresh + 1);
46 },
47 );
48
49 let on_limit = use_callback(
50 (refresh.clone(), limit.setter()),
51 |limit, (refresh, limit_setter)| {
52 limit_setter.set(limit);
53 refresh.set(**refresh + 1);
54 },
55 );
56
57 let on_switch_view_consumer = use_callback(
58 (refresh.clone(), switch_view_consumer.setter()),
59 |switch, (refresh, switch_setter)| {
60 switch_setter.set(switch);
61 refresh.set(**refresh + 1);
62 },
63 );
64
65 let on_statuses = use_callback(
66 (refresh.clone(), statuses.setter()),
67 |statuses, (refresh, statuses_setter)| {
68 statuses_setter.set(statuses);
69 refresh.set(**refresh + 1);
70 },
71 );
72
73 let fallback = html! {
74 <Bullseye>
75 <Spinner size={SpinnerSize::Lg} />
76 </Bullseye>
77 };
78
79 html!(
80 <Stack gutter=true>
81 <StackItem>
82 <Split gutter=true>
83 <SplitItem fill=true>
84 <Title level={Level::H3} size={Size::XXLarge}>{ "List Contract Negotiations" }</Title>
85 </SplitItem>
86 </Split>
87 </StackItem>
88 <StackItem>
89 <Suspense {fallback}>
90 <ContractNegotiationPageInner
91 offset={*offset}
92 limit={*limit}
93 switch_view_consumer={*switch_view_consumer}
94 statuses={(*statuses).clone()}
95 {on_offset}
96 {on_limit}
97 {on_switch_view_consumer}
98 {on_statuses}
99 force_refresh={*refresh}
100 on_show_contract_negotiation={props.on_show_contract_negotiation.clone()}
101 />
102 </Suspense>
103 </StackItem>
104 </Stack>
105 )
106}
107
108#[derive(Clone, Debug, PartialEq, Properties)]
109pub struct ContractNegotiationPageInnerProps {
110 pub offset: usize,
111 pub limit: usize,
112 pub switch_view_consumer: bool,
113 #[prop_or_default]
114 pub statuses: Vec<(String, bool)>,
115 pub on_offset: Callback<usize>,
116 pub on_limit: Callback<usize>,
117 pub on_switch_view_consumer: Callback<bool>,
118 pub on_statuses: Callback<Vec<(String, bool)>>,
119 pub force_refresh: usize,
120 pub on_show_contract_negotiation: Callback<String>,
121}
122
123#[component]
124pub fn ContractNegotiationPageInner(props: &ContractNegotiationPageInnerProps) -> HtmlResult {
125 let edc_connector_context = use_edc_connector_context();
126
127 let contract_negotiation_items = use_future_with(
128 (
129 edc_connector_context,
130 props.limit,
131 props.offset,
132 props.switch_view_consumer,
133 props.statuses.clone(),
134 props.force_refresh,
135 ),
136 |parameters| async move {
137 let (edc_connector_context, limit, offset, switch_view_consumer, statuses, _) =
138 (*parameters).clone();
139
140 let query_builder = Query::builder()
141 .limit(limit as u32)
142 .offset(offset as u32)
143 .filter(
144 "type",
145 "=",
146 if switch_view_consumer {
147 "CONSUMER"
148 } else {
149 "PROVIDER"
150 },
151 );
152
153 let query_builder = if statuses.iter().all(|(_, selected)| *selected)
154 || statuses.iter().all(|(_, selected)| !*selected)
155 {
156 query_builder
157 } else {
158 let list = statuses
159 .iter()
160 .filter_map(|(label, selected)| {
161 if *selected {
162 Some(label.clone().to_uppercase())
163 } else {
164 None
165 }
166 })
167 .collect::<Vec<_>>();
168
169 query_builder.filter("state", "IN", list)
170 };
171
172 let query = query_builder.build();
173
174 if let Some(client) = edc_connector_context.get_client() {
175 client
176 .contract_negotiations(EdcConnectorApiVersion::V4)
177 .query(query)
178 .await
179 .unwrap_or_default()
180 .into_iter()
181 .map(ContractNegotiationItem::from)
182 .collect()
183 } else {
184 vec![]
185 }
186 },
187 )?;
188
189 let contract_negotiation_items = (*contract_negotiation_items).clone();
190
191 Ok(html!(
192 <ListContractNegotiations
193 contract_negotiation_items={contract_negotiation_items}
194 offset={props.offset}
195 limit={props.limit}
196 switch={props.switch_view_consumer}
197 statuses={props.statuses.clone()}
198 on_offset={props.on_offset.clone()}
199 on_limit={props.on_limit.clone()}
200 on_switch_view_consumer={props.on_switch_view_consumer.clone()}
201 on_show_contract_negotiation={props.on_show_contract_negotiation.clone()}
202 on_statuses={props.on_statuses.clone()}
203 />
204 ))
205}