Skip to content

Commit

Permalink
fix: display unsupported operators in overrides UI and enhance context
Browse files Browse the repository at this point in the history
form
  • Loading branch information
sauraww committed Sep 6, 2024
1 parent f6519ef commit 7e1353d
Show file tree
Hide file tree
Showing 16 changed files with 796 additions and 590 deletions.
136 changes: 50 additions & 86 deletions crates/frontend/src/components/condition_pills.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use crate::components::condition_pills::types::ConditionOperator;

use self::types::Condition;
use leptos::{leptos_dom::helpers::WindowListenerHandle, *};
use serde_json::Value;
use wasm_bindgen::JsCast;
use web_sys::Element;

Expand Down Expand Up @@ -58,8 +59,27 @@ pub fn condition_expression(
} else {
("condition-item-collapsed", "condition-value-collapsed")
};
let Condition { left_operand: dimension, operator, right_operand: value } = condition
.get_value();

// Destructure the condition
let Condition { left_operand: dimension, operator, right_operand: value } = condition.get_value();

// Filter and convert values to strings for rendering
let filtered_vals: Vec<String> = value.into_iter().filter_map(|v|
match v {
Value::String(s) => Some(s.to_string()),
Value::Number(n) => Some(n.to_string()),
Value::Bool(b) => Some(b.to_string()),
Value::Array(arr) => {
Some(arr.iter().map(|v| v.to_string()).collect::<Vec<String>>().join(","))
}
Value::Object(o) => {
serde_json::to_string_pretty(&o).ok()
}
_ => None,
}
).collect();

// Render based on the operator type
view! {
<li
id=id.get_value()
Expand All @@ -78,36 +98,37 @@ pub fn condition_expression(
{operator.to_string()}
</span>

{match operator {
ConditionOperator::Between => {
let split_val: Vec<String> = value
.clone()
.split(',')
.map(String::from)
.collect();
view! {
<>
<span class="font-mono font-semibold context_condition">
{&split_val[0]}
</span>
<span class="font-mono font-medium text-gray-650 context_condition ">
{"and"}
</span>
<span class="font-mono font-semibold context_condition">
{&split_val[1]}
{
match operator {
ConditionOperator::Between => {
if filtered_vals.len() == 2 {
view! {
<>
<span class="font-mono font-semibold context_condition">
{&filtered_vals[0]}
</span>
<span class="font-mono font-medium text-gray-650 context_condition">
{"and"}
</span>
<span class="font-mono font-semibold context_condition">
{&filtered_vals[1]}
</span>
</>
}.into_view()
} else {
view! { <span class="font-mono text-red-500">"Invalid between values"</span> }.into_view()
}
},
_ => {
let rendered_value = filtered_vals.join(", ");
view! {
<span class=value_class>
{rendered_value}
</span>
</>
}
}
_ => {
view! {
<>
<span class=value_class>{value}</span>
</>
}.into_view()
}
}
}}

}
</li>
}
}}
Expand Down Expand Up @@ -149,60 +170,3 @@ pub fn condition(
</div>
}
}

#[component]
pub fn condition_pills(#[prop(into)] conditions: Vec<Condition>) -> impl IntoView {
view! {
{conditions
.into_iter()
.map(|condition| {
let dimension = condition.left_operand;
let op = condition.operator;
let val = condition.right_operand;
view! {
<span class="inline-flex items-center rounded-md bg-gray-50 px-2 py-1 text-xs ring-1 ring-inset ring-purple-700/10 shadow-md gap-x-2">
<span class="font-mono font-medium context_condition text-gray-500">
{dimension}
</span>
<span class="font-mono font-medium text-gray-650 context_condition ">
{op.to_string()}
</span>

{match op {
ConditionOperator::Between => {
let split_val: Vec<String> = val
.clone()
.split(',')
.map(String::from)
.collect();
view! {
<>
<span class="font-mono font-semibold context_condition">
{&split_val[0]}
</span>
<span class="font-mono font-medium text-gray-650 context_condition ">
{"and"}
</span>
<span class="font-mono font-semibold context_condition">
{&split_val[1]}
</span>
</>
}
}
_ => {
view! {
<>
<span class="font-mono font-semibold context_condition">
{val}
</span>
</>
}
}
}}

</span>
}
})
.collect::<Vec<_>>()}
}
}
38 changes: 17 additions & 21 deletions crates/frontend/src/components/condition_pills/types.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use std::fmt::Display;

use serde::{Deserialize, Serialize};
use serde_json::{Map, Value};

use crate::types::Context;

#[derive(Debug, Clone)]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum ConditionOperator {
Is,
In,
Expand All @@ -25,6 +26,18 @@ impl Display for ConditionOperator {
}
}

impl From<String> for ConditionOperator {
fn from(op: String) -> Self {
match op.as_str() {
"==" => ConditionOperator::Is,
"<=" => ConditionOperator::Between,
"in" => ConditionOperator::In,
"has" => ConditionOperator::Has,
other => ConditionOperator::Other(other.to_string()),
}
}
}

impl From<(String, &Vec<Value>)> for ConditionOperator {
fn from(value: (String, &Vec<Value>)) -> Self {
let (operator, operands) = value;
Expand All @@ -50,11 +63,11 @@ impl From<(String, &Vec<Value>)> for ConditionOperator {
}
}

#[derive(Clone)]
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Condition {
pub left_operand: String,
pub operator: ConditionOperator,
pub right_operand: String,
pub right_operand: Vec<Value>,
}

impl TryFrom<&Map<String, Value>> for Condition {
Expand All @@ -76,27 +89,10 @@ impl TryFrom<&Map<String, Value>> for Condition {
})
.unwrap_or("");

let other_operands = operands
.iter()
.filter_map(|item| {
if item.is_object() && item.as_object().unwrap().contains_key("var") {
return None;
}

match item {
Value::Null => String::from("null"),
Value::String(v) => v.clone(),
_ => format!("{}", item),
}
.into()
})
.collect::<Vec<String>>()
.join(",");

return Ok(Condition {
operator,
left_operand: dimension_name.to_owned(),
right_operand: other_operands,
right_operand: operands.to_vec(),
});
}

Expand Down
63 changes: 39 additions & 24 deletions crates/frontend/src/components/context_card.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::components::condition_pills::types::ConditionOperator;
use leptos::*;
use serde_json::{Map, Value};

Expand Down Expand Up @@ -25,6 +26,7 @@ pub fn context_card(
#[prop(default=Callback::new(|_| {}))] handle_delete: Callback<String, ()>,
) -> impl IntoView {
let conditions: Vec<Condition> = (&context).try_into().unwrap_or(vec![]);

let override_table_rows = overrides
.clone()
.into_iter()
Expand All @@ -35,55 +37,68 @@ pub fn context_card(
})
.collect::<Vec<Map<String, Value>>>();

let context_id = StoredValue::new(context.id.clone());
let context = StoredValue::new(context);
let overrides = StoredValue::new(overrides);
// Clone context and overrides for use in event handlers
let context_id = store_value(context.id.clone());
let context = store_value(context);
let overrides = store_value(overrides);

let table_columns = vec![
Column::default("KEY".to_string()),
Column::default("VALUE".to_string()),
];

let edit_unsupported = conditions
.iter()
.any(|condition| matches!(condition.operator, ConditionOperator::Other(_)));

view! {
<div class="rounded-lg shadow bg-base-100 p-6 shadow flex flex-col gap-4">
<div class="rounded-lg shadow bg-base-100 p-6 flex flex-col gap-4">
<div class="flex justify-between">
<h3 class="card-title text-base timeline-box text-gray-800 bg-base-100 shadow-md font-mono m-0 w-max">
"Condition"
</h3>
<Show when=move || show_actions>
<div class="h-fit text-right space-x-4">
<i
class="ri-pencil-line ri-lg text-blue-500 cursor-pointer"
on:click=move |_| {
handle_edit.call((context.get_value(), overrides.get_value()))
}
>
</i>
<i
class="ri-file-copy-line ri-lg text-blue-500 cursor-pointer"
on:click=move |_| {
handle_clone.call((context.get_value(), overrides.get_value()))
}
>
</i>
<div class="h-fit text-right space-x-4">
<Show when=move || !edit_unsupported.clone()>
<i
class="ri-pencil-line ri-lg text-blue-500 cursor-pointer"
on:click=move |_| {
handle_edit.call((context.get_value(), overrides.get_value()));
}
/>
<i
class="ri-file-copy-line ri-lg text-blue-500 cursor-pointer"
on:click=move |_| {
handle_clone.call((context.get_value(), overrides.get_value()));
}
/>
</Show>
<Show when=move || edit_unsupported.clone()>
<span class="badge badge-warning text-xs ml-2 flex items-center">
{"Edit Unsupported"}
</span>
</Show>
<i
class="ri-delete-bin-5-line ri-lg text-red-500 cursor-pointer"
on:click=move |_| { handle_delete.call(context.get_value().id) }
></i>
on:click=move |_| {
let context_id = context_id.get_value();
handle_delete.call(context_id);
}
/>
</div>
</Show>
</div>

<div class="pl-5">
<ConditionComponent
conditions=conditions
conditions=conditions // Clone only once before reusing in multiple closures
id=context_id.get_value()
class="xl:w-[400px] h-fit"
/>
<Table
cell_class="min-w-48 font-mono".to_string()
rows=override_table_rows
key_column="id".to_string()
key_column="KEY".to_string()
columns=table_columns
/>
</div>
Expand Down
Loading

0 comments on commit 7e1353d

Please sign in to comment.