edc_web_components/components/
list_contract_negotiations.rs1use crate::models::ContractNegotiationItem;
2use patternfly_yew::prelude::*;
3use std::rc::Rc;
4use yew::prelude::*;
5
6#[derive(Clone, Debug, PartialEq, Properties)]
7pub struct ListContractNegotiationsProps {
8 pub contract_negotiation_items: Vec<ContractNegotiationItem>,
9 pub offset: usize,
10 pub limit: usize,
11 pub switch: bool,
12 pub on_offset: Callback<usize>,
13 pub on_limit: Callback<usize>,
14 pub on_switch_view_consumer: Callback<bool>,
15 pub on_show_contract_negotiation: Callback<String>,
16}
17
18#[component]
19pub fn ListContractNegotiations(props: &ListContractNegotiationsProps) -> Html {
20 let header = html_nested! {
21 <TableHeader<Columns>>
22 <TableColumn<Columns> label="State" index={Columns::State} />
23 <TableColumn<Columns> label="Contract Agreement ID" index={Columns::ContractAgreementId} />
24 <TableColumn<Columns> label="Counter Party ID" index={Columns::CounterPartyId} />
25 <TableColumn<Columns> label="Protocol" index={Columns::Protocol} />
26 <TableColumn<Columns> label="Kind" index={Columns::Kind} />
27 <TableColumn<Columns> label="" index={Columns::Actions} />
28 </TableHeader<Columns>>
29 };
30
31 let total_entries: Option<usize> = None;
32
33 let nav_callback = use_callback(
34 (
35 props.offset,
36 props.limit,
37 total_entries,
38 props.on_offset.clone(),
39 ),
40 |page: Navigation, (offset, limit, total_entries, on_offset)| {
41 let offset = match page {
42 Navigation::First => 0,
43 Navigation::Last => (total_entries.unwrap_or_default().saturating_sub(1) / limit) * limit,
44 Navigation::Previous => *offset - limit,
45 Navigation::Next => *offset + limit,
46 Navigation::Page(n) => n * limit,
47 };
48 on_offset.emit(offset);
49 },
50 );
51
52 let rows = props
53 .contract_negotiation_items
54 .iter()
55 .map(
56 |contract_negotiation_item| ContractNegotiationItemRenderer {
57 item: contract_negotiation_item.clone(),
58 on_show_contract_negotiation: props.on_show_contract_negotiation.clone(),
59 },
60 )
61 .collect();
62
63 let (entries, _) = use_table_data(MemoizedTableModel::new(Rc::new(rows)));
64
65 html!(
66 <>
67 <Toolbar>
68 <ToolbarContent>
69 <ToolbarItem r#type={ToolbarItemType::Pagination}>
70 <Switch
71 label="as Consumer"
72 label_off="as Provider"
73 onchange={props.on_switch_view_consumer.clone()}
74 />
75 <Pagination
76 offset={props.offset}
77 entries_per_page_choices={vec![5, 10, 25, 50, 100]}
78 selected_choice={props.limit}
79 onlimit={&props.on_limit}
80 onnavigation={&nav_callback}
81 />
82 </ToolbarItem>
83 </ToolbarContent>
84 </Toolbar>
85 <Table<Columns, UseTableData<Columns, MemoizedTableModel<ContractNegotiationItemRenderer>>>
86 mode={TableMode::Compact}
87 {header}
88 {entries}
89 />
90 </>
91 )
92}
93
94#[derive(Clone, Debug, Eq, PartialEq)]
95enum Columns {
96 State,
97 ContractAgreementId,
98 CounterPartyId,
99 Protocol,
100 Kind,
101 Actions,
102}
103
104#[derive(Clone, Debug)]
105struct ContractNegotiationItemRenderer {
106 item: ContractNegotiationItem,
107 on_show_contract_negotiation: Callback<String>,
108}
109
110impl TableEntryRenderer<Columns> for ContractNegotiationItemRenderer {
111 fn render_cell(&self, context: CellContext<'_, Columns>) -> Cell {
112 match context.column {
113 Columns::State => html! { <Label label={self.item.state.to_string()} color={Color::Blue} /> },
114 Columns::ContractAgreementId => html! { self.item.contract_agreement_id.to_string() },
115 Columns::CounterPartyId => html! { self.item.counter_party_id.to_string() },
116 Columns::Protocol => html! { self.item.protocol.to_string() },
117 Columns::Kind => html! { self.item.kind.to_string() },
118 Columns::Actions => {
119 let contract_negotiation_id = self.item.id.clone();
120 html! {
121 <Button
122 variant={ButtonVariant::Primary}
123 onclick={self.on_show_contract_negotiation.clone().reform(move |_| contract_negotiation_id.clone())}
124 icon={Icon::Eye}
125 >
126 { "Show" }
127 </Button>
128 }
129 },
130 }
131 .into()
132 }
133}