edc_web_components/components/create_policy/
rule.rs1use 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}