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