edc_web_ui/components/
list_contract_negotiations.rs

1use crate::contexts::use_edc_connector_context;
2use edc_connector_client::types::contract_negotiation::{
3  ContractNegotiation, ContractNegotiationKind, ContractNegotiationState,
4};
5use edc_connector_client::types::query::Query;
6use patternfly_yew::prelude::*;
7use std::rc::Rc;
8use yew::prelude::*;
9use yew::suspense::use_future_with;
10
11#[function_component]
12pub fn ListContractNegotiations() -> Html {
13  let fallback = html!("Loading ...");
14
15  html!(
16    <Suspense {fallback}>
17      <ListContractNegotiationsInner />
18    </Suspense>
19  )
20}
21
22#[function_component]
23pub fn ListContractNegotiationsInner() -> HtmlResult {
24  let edc_connector_context = use_edc_connector_context();
25
26  let offset = use_state(|| 0usize);
27  let limit = use_state(|| 10usize);
28
29  let contract_negotiation_list = use_future_with(
30    (edc_connector_context, *limit, *offset),
31    |parameters| async move {
32      let (edc_connector_context, limit, offset) = &*parameters;
33
34      let query = Query::builder()
35        .limit(*limit as u32)
36        .offset(*offset as u32)
37        .build();
38
39      if let Some(client) = edc_connector_context.get_client() {
40        client.contract_negotiations().query(query).await
41      } else {
42        Ok(vec![])
43      }
44    },
45  )?;
46
47  let contract_negotiation_list = &(*contract_negotiation_list);
48
49  let header = html_nested! {
50    <TableHeader<Columns>>
51      <TableColumn<Columns> label="ID" index={Columns::Id} />
52      <TableColumn<Columns> label="Access Policy ID" index={Columns::AccessPolicyId} />
53      <TableColumn<Columns> label="Contract Policy ID" index={Columns::ContractPolicyId} />
54      <TableColumn<Columns> label="State" index={Columns::State} />
55      <TableColumn<Columns> label="Contract Agreement ID" index={Columns::ContractAgreementId} />
56      <TableColumn<Columns> label="Counter Party ID" index={Columns::CounterPartyId} />
57      <TableColumn<Columns> label="Counter Party Address" index={Columns::CounterPartyAddress} />
58      <TableColumn<Columns> label="Protocol" index={Columns::Protocol} />
59      <TableColumn<Columns> label="Kind" index={Columns::Kind} />
60    </TableHeader<Columns>>
61  };
62
63  let limit_callback = use_callback(limit.clone(), |number, limit| limit.set(number));
64
65  let total_entries: Option<usize> = None;
66
67  let nav_callback = use_callback(
68    (offset.clone(), *limit, total_entries),
69    |page: Navigation, (offset, limit, total_entries)| {
70      let o = match page {
71        Navigation::First => 0,
72        Navigation::Last => (total_entries.unwrap_or_default().saturating_sub(1) / limit) * limit,
73        Navigation::Previous => **offset - limit,
74        Navigation::Next => **offset + limit,
75        Navigation::Page(n) => n * limit,
76      };
77      offset.set(o);
78    },
79  );
80
81  let rows = contract_negotiation_list
82    .as_ref()
83    .unwrap()
84    .iter()
85    .map(|contract_negotiation| ContractNegotiationRenderer(contract_negotiation.clone()))
86    .collect();
87
88  let (entries, _) = use_table_data(MemoizedTableModel::new(Rc::new(rows)));
89
90  let table = html!(
91    <>
92      <Toolbar>
93        <ToolbarContent>
94          <ToolbarItem r#type={ToolbarItemType::Pagination}>
95            <Pagination
96              offset={*offset}
97              entries_per_page_choices={vec![5, 10, 25, 50, 100]}
98              selected_choice={*limit}
99              onlimit={&limit_callback}
100              onnavigation={&nav_callback}
101            />
102          </ToolbarItem>
103        </ToolbarContent>
104      </Toolbar>
105      <Table<Columns, UseTableData<Columns, MemoizedTableModel<ContractNegotiationRenderer>>>
106        mode={TableMode::Compact}
107        {header}
108        {entries}
109        />
110    </>
111  );
112
113  Ok(table)
114}
115
116#[derive(Clone, Debug, Eq, PartialEq)]
117enum Columns {
118  Id,
119  AccessPolicyId,
120  ContractPolicyId,
121  State,
122  ContractAgreementId,
123  CounterPartyId,
124  CounterPartyAddress,
125  Protocol,
126  Kind,
127}
128
129#[derive(Clone, Debug)]
130struct ContractNegotiationRenderer(ContractNegotiation);
131
132impl ContractNegotiationRenderer {}
133
134impl TableEntryRenderer<Columns> for ContractNegotiationRenderer {
135  fn render_cell(&self, context: CellContext<'_, Columns>) -> Cell {
136    let contract_agreement_id = self
137      .0
138      .contract_agreement_id()
139      .map(|contract_agreement_id| contract_agreement_id.to_string())
140      .unwrap_or_default();
141
142    let kind = match self.0.kind() {
143      ContractNegotiationKind::Consumer => "Consumer",
144      ContractNegotiationKind::Provider => "Provider",
145    };
146
147    let state = match self.0.state() {
148      ContractNegotiationState::Initial => "Initial".to_string(),
149      ContractNegotiationState::Requesting => "Requesting".to_string(),
150      ContractNegotiationState::Requested => "Requested".to_string(),
151      ContractNegotiationState::Offering => "Offering".to_string(),
152      ContractNegotiationState::Offered => "Offered".to_string(),
153      ContractNegotiationState::Accepting => "Accepting".to_string(),
154      ContractNegotiationState::Accepted => "Accepted".to_string(),
155      ContractNegotiationState::Agreeing => "Agreeing".to_string(),
156      ContractNegotiationState::Agreed => "Agreed".to_string(),
157      ContractNegotiationState::Verifying => "Verifying".to_string(),
158      ContractNegotiationState::Verified => "Verified".to_string(),
159      ContractNegotiationState::Finalizing => "Finalizing".to_string(),
160      ContractNegotiationState::Finalized => "Finalized".to_string(),
161      ContractNegotiationState::Terminating => "Terminating".to_string(),
162      ContractNegotiationState::Terminated => "Terminated".to_string(),
163      ContractNegotiationState::Other(other) => other.to_string(),
164    };
165
166    match context.column {
167      Columns::Id => html! {self.0.id().to_string()},
168      Columns::AccessPolicyId => html! {},
169      Columns::ContractPolicyId => html! {},
170      Columns::State => html! { state },
171      Columns::ContractAgreementId => html! { contract_agreement_id },
172      Columns::CounterPartyId => html! { self.0.counter_party_id() },
173      Columns::CounterPartyAddress => html! { self.0.counter_party_address() },
174      Columns::Protocol => html! { self.0.protocol() },
175      Columns::Kind => html! { kind },
176    }
177    .into()
178  }
179}