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
109 policy_id={self.contract_definition_item.access_policy_id.to_string()}
110 show_with_modal=true
111 />
112 )
113 },
114 Columns::ContractPolicy => {
115 html!(
116 <PolicyReference
117 policy_id={self.contract_definition_item.contract_policy_id.to_string()}
118 show_with_modal=true
119 />
120 )
121 },
122 Columns::Assets => {
123 let assets = self.contract_definition_item.asset_ids.iter().map(|asset_id| {
124 html_nested!(
125 <FlexItem>
126 <AssetReference asset_id={asset_id.clone()} />
127 </FlexItem>
128 )
129 });
130
131 html!(<Flex>{ for assets }</Flex>)
132 },
133 Columns::Actions => {
134 let contract_definition_id = self.contract_definition_item.id.to_string();
135
136 html!(<DeleteContractDefinition {contract_definition_id} ondelete={self.ondelete.clone()} />)
137 }
138 }
139 .into()
140 }
141}
142
143#[derive(Clone, PartialEq, Properties)]
144pub struct Props {
145 pub contract_definition_id: String,
146 pub ondelete: Callback<String>,
147}
148
149#[function_component]
150pub fn DeleteContractDefinition(props: &Props) -> Html {
151 let onclick = use_callback(
152 (props.ondelete.clone(), props.contract_definition_id.clone()),
153 move |_, (ondelete, contract_definition_id)| {
154 ondelete.emit(contract_definition_id.to_string());
155 },
156 );
157
158 html!(<Button variant={ButtonVariant::Danger} icon={Icon::Trash} {onclick}>{ "Delete" }</Button>)
159}