Skip to main content

edc_web_components/components/
list_contract_definitions.rs

1use 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}