edc_web_components/components/
list_contract_definitions.rs1use crate::components::{AssetReference, PolicyReference};
2use crate::models::ContractDefinitionItem;
3use patternfly_yew::prelude::*;
4use std::rc::Rc;
5use yew::prelude::*;
6
7#[derive(Clone, Debug, PartialEq, Properties)]
8pub struct ListContractDefinitionsProps {
9 pub contract_definition_items: Vec<ContractDefinitionItem>,
10 pub offset: usize,
11 pub limit: usize,
12 pub onoffset: Callback<usize>,
13 pub onlimit: Callback<usize>,
14 pub ondelete: Callback<String>,
15}
16
17#[component]
18pub fn ListContractDefinitions(props: &ListContractDefinitionsProps) -> Html {
19 let header = html_nested! {
20 <TableHeader<Columns>>
21 <TableColumn<Columns> label="Name" index={Columns::Name} />
22 <TableColumn<Columns> label="Access Policy" index={Columns::AccessPolicy} />
23 <TableColumn<Columns> label="Contract Policy" index={Columns::ContractPolicy} />
24 <TableColumn<Columns> label="Assets" index={Columns::Assets} />
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_definition_items
52 .iter()
53 .map(|contract_definition_item| ContractDefinitionItemRenderer {
54 contract_definition_item: contract_definition_item.clone(),
55 ondelete: props.ondelete.clone(),
56 })
57 .collect();
58
59 let (entries, _) = use_table_data(MemoizedTableModel::new(Rc::new(rows)));
60
61 html!(
62 <>
63 <Toolbar>
64 <ToolbarContent>
65 <ToolbarItem r#type={ToolbarItemType::Pagination}>
66 <Pagination
67 offset={props.offset}
68 entries_per_page_choices={vec![5, 10, 25, 50, 100]}
69 selected_choice={props.limit}
70 onlimit={&props.onlimit}
71 onnavigation={&nav_callback}
72 />
73 </ToolbarItem>
74 </ToolbarContent>
75 </Toolbar>
76 <Table<Columns, UseTableData<Columns, MemoizedTableModel<ContractDefinitionItemRenderer>>>
77 mode={TableMode::Compact}
78 {header}
79 {entries}
80 />
81 </>
82 )
83}
84
85#[derive(Clone, Debug, Eq, PartialEq)]
86enum Columns {
87 Name,
88 AccessPolicy,
89 ContractPolicy,
90 Assets,
91 Actions,
92}
93
94#[derive(Clone, Debug)]
95struct ContractDefinitionItemRenderer {
96 contract_definition_item: ContractDefinitionItem,
97 ondelete: Callback<String>,
98}
99
100impl ContractDefinitionItemRenderer {}
101
102impl TableEntryRenderer<Columns> for ContractDefinitionItemRenderer {
103 fn render_cell(&self, context: CellContext<'_, Columns>) -> Cell {
104 match context.column {
105 Columns::Name => html! { self.contract_definition_item.name.to_string() },
106 Columns::AccessPolicy => {
107 html!(
108 <PolicyReference policy_id={self.contract_definition_item.access_policy_id.to_string()} />
109 )
110 },
111 Columns::ContractPolicy => {
112 html!(
113 <PolicyReference
114 policy_id={self.contract_definition_item.contract_policy_id.to_string()}
115 />
116 )
117 },
118 Columns::Assets => {
119 let assets = self.contract_definition_item.asset_ids.iter().map(|asset_id| {
120 html_nested!(
121 <FlexItem>
122 <AssetReference asset_id={asset_id.clone()} />
123 </FlexItem>
124 )
125 });
126
127 html!(<Flex>{ for assets }</Flex>)
128 },
129 Columns::Actions => {
130 let contract_definition_id = self.contract_definition_item.id.to_string();
131
132 html!(<DeleteContractDefinition {contract_definition_id} ondelete={self.ondelete.clone()} />)
133 }
134 }
135 .into()
136 }
137}
138
139#[derive(Clone, PartialEq, Properties)]
140pub struct Props {
141 pub contract_definition_id: String,
142 pub ondelete: Callback<String>,
143}
144
145#[function_component]
146pub fn DeleteContractDefinition(props: &Props) -> Html {
147 let onclick = use_callback(
148 (props.ondelete.clone(), props.contract_definition_id.clone()),
149 move |_, (ondelete, contract_definition_id)| {
150 ondelete.emit(contract_definition_id.to_string());
151 },
152 );
153
154 html!(<Button variant={ButtonVariant::Danger} icon={Icon::Trash} {onclick}>{ "Delete" }</Button>)
155}