edc_web_ui/components/
list_contract_negotiations.rs1use 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}