Skip to main content

edc_web_components/components/create_policy/
rule.rs

1use crate::components::create_policy::atomic_constraint_edit::{
2  AtomicConstraintEdit, ConstraintMode,
3};
4use crate::components::simple_or_id_field::SimpleOrIdField;
5use edc_connector_client::types::policy::{Action, AtomicConstraint, Constraint};
6use edc_connector_client::types::properties::PropertyValue;
7use patternfly_yew::prelude::*;
8use yew::prelude::*;
9
10pub type UpdatedRule = (usize, Action, Vec<(ConstraintMode, Constraint)>);
11
12#[derive(Clone, PartialEq, Properties)]
13pub struct Props {
14  pub index: usize,
15  pub action: Action,
16  pub constraints: Vec<(ConstraintMode, Constraint)>,
17  pub onchange: Callback<UpdatedRule>,
18  pub ondelete: Callback<usize>,
19}
20
21#[component]
22pub fn Rule(props: &Props) -> Html {
23  let action = use_state(|| props.action.clone());
24  let constraints = use_state(|| props.constraints.clone());
25
26  let onchange_action = {
27    let action = action.clone();
28
29    use_callback(
30      (constraints.clone(), props.index, props.onchange.clone()),
31      move |(is_simple, value), (constraints, index, onchange)| {
32        let value = if is_simple {
33          Action::Simple(value)
34        } else {
35          Action::Id { id: value }
36        };
37
38        action.set(value.clone());
39        onchange.emit((*index, value, (**constraints).clone()));
40      },
41    )
42  };
43
44  let add_constraint = use_callback(
45    (
46      action.clone(),
47      constraints.clone(),
48      props.index,
49      props.onchange.clone(),
50    ),
51    |_, (action, constraints, index, onchange)| {
52      let mut list = (**constraints).clone();
53
54      list.push((
55        ConstraintMode::Cel,
56        Constraint::Atomic(AtomicConstraint::new("", "eq", "")),
57      ));
58      constraints.set(list.clone());
59
60      onchange.emit((*index, (**action).clone(), list));
61    },
62  );
63
64  let delete_constraint = use_callback(
65    (
66      action.clone(),
67      constraints.clone(),
68      props.index,
69      props.onchange.clone(),
70    ),
71    move |contraint_index, (action, constraints, index, onchange)| {
72      let mut list = (**constraints).clone();
73      list.remove(contraint_index);
74      constraints.set(list.clone());
75
76      onchange.emit((*index, (**action).clone(), list));
77    },
78  );
79
80  let delete_rule = use_callback(
81    (props.index, props.ondelete.clone()),
82    |_, (index, ondelete)| {
83      ondelete.emit(*index);
84    },
85  );
86
87  let update_constraint = use_callback(
88    (
89      action.clone(),
90      constraints.clone(),
91      props.index,
92      props.onchange.clone(),
93    ),
94    |(id, constraint_mode, left_operand, operator, right_operand),
95     (action, constraints, index, onchange)| {
96      let mut list = (**constraints).clone();
97
98      list[id] = (
99        constraint_mode,
100        Constraint::Atomic(AtomicConstraint {
101          left_operand,
102          operator,
103          right_operand: PropertyValue(right_operand),
104        }),
105      );
106
107      constraints.set(list.clone());
108
109      onchange.emit((*index, (**action).clone(), list));
110    },
111  );
112
113  let list_of_constraints = (*constraints)
114    .iter()
115    .enumerate()
116    .map(|(index, constraint)| {
117      let inner = match constraint {
118        (constraint_mode, Constraint::Atomic(atomic_constraint)) => {
119          html!(
120            <AtomicConstraintEdit
121              key={index}
122              {index}
123              constraint_mode={*constraint_mode}
124              left_operand={atomic_constraint.left_operand.clone()}
125              operator={atomic_constraint.operator.clone()}
126              right_operand={atomic_constraint.right_operand.0.clone()}
127              onchange={update_constraint.clone()}
128              ondelete={delete_constraint.clone()}
129            />
130          )
131        }
132        (_, Constraint::MultiplicityConstraint(_)) => {
133          html!()
134        }
135      };
136
137      html_nested!(<StackItem>{ inner }</StackItem>)
138    });
139
140  let (action_is_simple, action_value) = match (*action).clone() {
141    Action::Simple(value) => (true, value),
142    Action::Id { id } => (false, id),
143  };
144
145  html!(
146    <Stack gutter=true>
147      { for list_of_constraints }
148      <StackItem>
149        <Button icon={Icon::Plus} variant={ButtonVariant::Primary} onclick={add_constraint}>
150          { "Add Constraint" }
151        </Button>
152      </StackItem>
153      <StackItem>
154        <SimpleOrIdField
155          onchange={onchange_action}
156          is_simple={action_is_simple}
157          value={action_value}
158        />
159      </StackItem>
160      <StackItem>
161        <Button icon={Icon::Trash} variant={ButtonVariant::DangerSecondary} onclick={delete_rule}>
162          { "Delete rule" }
163        </Button>
164      </StackItem>
165    </Stack>
166  )
167}