Skip to main content

edc_web_components/pages/
contract_negotiation_page.rs

1use 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, SortOrder};
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            <p>
86              { "A contract negotiation represents the active, multi-step process between two parties to agree on data sharing terms." }
87            </p>
88          </SplitItem>
89        </Split>
90      </StackItem>
91      <StackItem>
92        <Suspense {fallback}>
93          <ContractNegotiationPageInner
94            offset={*offset}
95            limit={*limit}
96            switch_view_consumer={*switch_view_consumer}
97            statuses={(*statuses).clone()}
98            {on_offset}
99            {on_limit}
100            {on_switch_view_consumer}
101            {on_statuses}
102            force_refresh={*refresh}
103            on_show_contract_negotiation={props.on_show_contract_negotiation.clone()}
104          />
105        </Suspense>
106      </StackItem>
107    </Stack>
108  )
109}
110
111#[derive(Clone, Debug, PartialEq, Properties)]
112pub struct ContractNegotiationPageInnerProps {
113  pub offset: usize,
114  pub limit: usize,
115  pub switch_view_consumer: bool,
116  #[prop_or_default]
117  pub statuses: Vec<(String, bool)>,
118  pub on_offset: Callback<usize>,
119  pub on_limit: Callback<usize>,
120  pub on_switch_view_consumer: Callback<bool>,
121  pub on_statuses: Callback<Vec<(String, bool)>>,
122  pub force_refresh: usize,
123  pub on_show_contract_negotiation: Callback<String>,
124}
125
126#[component]
127pub fn ContractNegotiationPageInner(props: &ContractNegotiationPageInnerProps) -> HtmlResult {
128  let edc_connector_context = use_edc_connector_context();
129
130  let contract_negotiation_items = use_future_with(
131    (
132      edc_connector_context,
133      props.limit,
134      props.offset,
135      props.switch_view_consumer,
136      props.statuses.clone(),
137      props.force_refresh,
138    ),
139    |parameters| async move {
140      let (edc_connector_context, limit, offset, switch_view_consumer, statuses, _) =
141        (*parameters).clone();
142
143      let query_builder = Query::builder()
144        .limit(limit as u32)
145        .offset(offset as u32)
146        .filter(
147          "type",
148          "=",
149          if switch_view_consumer {
150            "CONSUMER"
151          } else {
152            "PROVIDER"
153          },
154        );
155
156      let query_builder = if statuses.iter().all(|(_, selected)| *selected)
157        || statuses.iter().all(|(_, selected)| !*selected)
158      {
159        query_builder
160      } else {
161        let list = statuses
162          .iter()
163          .filter_map(|(label, selected)| {
164            if *selected {
165              Some(label.clone().to_uppercase())
166            } else {
167              None
168            }
169          })
170          .collect::<Vec<_>>();
171
172        query_builder.filter("state", "IN", list)
173      };
174
175      let query = query_builder.sort("createdAt", SortOrder::Desc).build();
176
177      if let Some(client) = edc_connector_context.get_client() {
178        client
179          .contract_negotiations(EdcConnectorApiVersion::V4)
180          .query(query)
181          .await
182          .unwrap_or_default()
183          .into_iter()
184          .map(ContractNegotiationItem::from)
185          .collect()
186      } else {
187        vec![]
188      }
189    },
190  )?;
191
192  let contract_negotiation_items = (*contract_negotiation_items).clone();
193
194  Ok(html!(
195    <ListContractNegotiations
196      contract_negotiation_items={contract_negotiation_items}
197      offset={props.offset}
198      limit={props.limit}
199      switch={props.switch_view_consumer}
200      statuses={props.statuses.clone()}
201      on_offset={props.on_offset.clone()}
202      on_limit={props.on_limit.clone()}
203      on_switch_view_consumer={props.on_switch_view_consumer.clone()}
204      on_show_contract_negotiation={props.on_show_contract_negotiation.clone()}
205      on_statuses={props.on_statuses.clone()}
206    />
207  ))
208}