Skip to main content

edc_web_components/components/
list_policies.rs

1use crate::models::PolicyDefinitionItem;
2use patternfly_yew::prelude::*;
3use std::rc::Rc;
4use yew::prelude::*;
5
6#[derive(Clone, Debug, PartialEq, Properties)]
7pub struct ListPoliciesProps {
8  pub policy_definition_items: Vec<PolicyDefinitionItem>,
9  pub offset: usize,
10  pub limit: usize,
11  pub onoffset: Callback<usize>,
12  pub onlimit: Callback<usize>,
13  pub ondelete: Callback<String>,
14  pub onshow: Callback<String>,
15}
16
17#[component]
18pub fn ListPolicies(props: &ListPoliciesProps) -> Html {
19  let header = html_nested! {
20    <TableHeader<Columns>>
21      <TableColumn<Columns> label="Name" index={Columns::Name} />
22      <TableColumn<Columns> label="Kind" index={Columns::Kind} />
23      <TableColumn<Columns> label="Assignee" index={Columns::Assignee} />
24      <TableColumn<Columns> label="Assigner" index={Columns::Assigner} />
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    .policy_definition_items
52    .iter()
53    .map(|policy_definition_item| PolicyDefinitionItemRenderer {
54      policy_definition_item: policy_definition_item.clone(),
55      ondelete: props.ondelete.clone(),
56      onshow: props.onshow.clone(),
57    })
58    .collect();
59
60  let (entries, _) = use_table_data(MemoizedTableModel::new(Rc::new(rows)));
61
62  html!(
63    <>
64      <Toolbar>
65        <ToolbarContent>
66          <ToolbarItem r#type={ToolbarItemType::Pagination}>
67            <Pagination
68              offset={props.offset}
69              entries_per_page_choices={vec![5, 10, 25, 50, 100]}
70              selected_choice={props.limit}
71              onlimit={&props.onlimit}
72              onnavigation={&nav_callback}
73            />
74          </ToolbarItem>
75        </ToolbarContent>
76      </Toolbar>
77      <Table<Columns, UseTableData<Columns, MemoizedTableModel<PolicyDefinitionItemRenderer>>>
78        mode={TableMode::Compact}
79        {header}
80        {entries}
81      />
82    </>
83  )
84}
85
86#[derive(Clone, Debug, Eq, PartialEq)]
87enum Columns {
88  Name,
89  Kind,
90  Assignee,
91  Assigner,
92  Actions,
93}
94
95#[derive(Clone, Debug)]
96struct PolicyDefinitionItemRenderer {
97  policy_definition_item: PolicyDefinitionItem,
98  ondelete: Callback<String>,
99  onshow: Callback<String>,
100}
101
102impl TableEntryRenderer<Columns> for PolicyDefinitionItemRenderer {
103  fn render_cell(&self, context: CellContext<'_, Columns>) -> Cell {
104    match context.column {
105      Columns::Name => html! { self.policy_definition_item.name.to_string() },
106      Columns::Kind => html! { self.policy_definition_item.kind.to_string() },
107      Columns::Assignee => html!(
108        self
109          .policy_definition_item
110          .assignee
111          .clone()
112          .unwrap_or_default()
113      ),
114      Columns::Assigner => html!(
115        self
116          .policy_definition_item
117          .assigner
118          .clone()
119          .unwrap_or_default()
120      ),
121      Columns::Actions => {
122        let policy_id = self.policy_definition_item.id.to_string();
123        let ondelete = self.ondelete.clone();
124        let onshow = self.onshow.clone();
125
126        html!(
127          <Split gutter=true>
128            <SplitItem>
129              <ShowPolicy policy_id={policy_id.clone()} {onshow} />
130            </SplitItem>
131            <SplitItem>
132              <DeletePolicy {policy_id} {ondelete} />
133            </SplitItem>
134          </Split>
135        )
136      }
137    }
138    .into()
139  }
140}
141
142#[derive(Clone, PartialEq, Properties)]
143pub struct DeletePolicyProps {
144  pub policy_id: String,
145  pub ondelete: Callback<String>,
146}
147
148#[function_component]
149pub fn DeletePolicy(props: &DeletePolicyProps) -> Html {
150  let onclick = use_callback(
151    (props.ondelete.clone(), props.policy_id.clone()),
152    move |_, (ondelete, policy_id)| {
153      ondelete.emit(policy_id.clone());
154    },
155  );
156
157  html!(<Button variant={ButtonVariant::Danger} icon={Icon::Trash} {onclick}>{ "Delete" }</Button>)
158}
159
160#[derive(Clone, PartialEq, Properties)]
161pub struct ShowPolicyProps {
162  pub policy_id: String,
163  pub onshow: Callback<String>,
164}
165
166#[function_component]
167pub fn ShowPolicy(props: &ShowPolicyProps) -> Html {
168  let onclick = use_callback(
169    (props.onshow.clone(), props.policy_id.clone()),
170    move |_, (onshow, policy_id)| {
171      onshow.emit(policy_id.clone());
172    },
173  );
174
175  html!(<Button variant={ButtonVariant::Primary} icon={Icon::Eye} {onclick}>{ "Show" }</Button>)
176}