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;
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}