Skip to content

Commit

Permalink
feat: Added grouping in default_config page
Browse files Browse the repository at this point in the history
  • Loading branch information
mahatoankitkumar committed Apr 23, 2024
1 parent 15840e7 commit a45be66
Show file tree
Hide file tree
Showing 3 changed files with 192 additions and 43 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ pub fn default_config_form<NF>(
#[prop(default = String::new())] config_pattern: String,
#[prop(default = String::new())] config_value: String,
#[prop(default = None)] function_name: Option<Value>,
#[prop(default = None)] prefix: Option<String>,
handle_submit: NF,
) -> impl IntoView
where
Expand Down Expand Up @@ -65,7 +66,9 @@ where

let on_submit = move |ev: MouseEvent| {
ev.prevent_default();
let f_name = config_key.get();
let f_name = prefix
.clone()
.map_or_else(|| config_key.get(), |p| p + &config_key.get());
let f_type = config_type.get();
let f_pattern = config_pattern.get();
let f_value = config_value.get();
Expand Down
223 changes: 181 additions & 42 deletions crates/frontend/src/pages/DefaultConfig/DefaultConfig.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ use crate::components::default_config_form::default_config_form::DefaultConfigFo
use crate::components::drawer::drawer::{close_drawer, open_drawer, Drawer, DrawerBtn};
use crate::components::stat::stat::Stat;
use crate::components::table::{table::Table, types::Column};
use crate::types::BreadCrums;
use leptos::*;
use leptos_router::{use_navigate, use_query_map};
use serde_json::{json, Map, Value};
use std::collections::HashMap;
use std::collections::{HashMap, HashSet};

#[derive(Clone, Debug, Default)]
pub struct RowData {
Expand All @@ -30,11 +32,37 @@ pub fn DefaultConfig() -> impl IntoView {
);

let selected_config = create_rw_signal::<Option<RowData>>(None);
let filters = create_rw_signal::<Option<String>>(None);
let query_params = use_query_map();

create_effect(move |_| {
let query_params_map = query_params.try_get();
if let Some(query_map) = query_params_map {
let opt_prefix = query_map.get("prefix");
if let Some(prefix) = opt_prefix {
filters.set(Some(prefix.to_string()));
} else {
filters.set(None);
}
}
});

let folder_click_handler = move |key_name: Option<String>| {
let tenant = tenant_rs.get();
let redirect_url = match key_name {
Some(prefix) => format!("admin/{tenant}/default-config?prefix={prefix}"),
None => format!("admin/{tenant}/default-config"),
};
logging::log!("redirecting to {:?}", redirect_url.clone());
let navigate = use_navigate();
navigate(redirect_url.as_str(), Default::default());
};

let table_columns = create_memo(move |_| {
let edit_col_formatter = move |_: &str, row: &Map<String, Value>| {
logging::log!("{:?}", row);
let row_key = row["key"].clone().to_string().replace("\"", "");
let key = row_key.clone();
let row_value = row["value"].clone().to_string().replace("\"", "");

let schema = row["schema"].clone().to_string();
Expand Down Expand Up @@ -116,10 +144,36 @@ pub fn DefaultConfig() -> impl IntoView {
let edit_icon: HtmlElement<html::I> =
view! { <i class="ri-pencil-line ri-xl text-blue-500"></i> };

view! { <span class="cursor-pointer" on:click=edit_click_handler>{edit_icon}</span> }.into_view()
if key.to_owned().contains(".") {
view! { <span>{"-"}</span> }.into_view()
} else {
view! { <span class="cursor-pointer" on:click=edit_click_handler>{edit_icon}</span> }.into_view()
}
};

let expand = move |_: &str, row: &Map<String, Value>| {
let key_name = row["key"].clone().to_string().replace("\"", "");
let key_name_copy = key_name.clone();

if key_name.contains(".") {
view! { <span class="cursor-pointer text-blue-500 underline underline-offset-2"
on:click=move |_| {
let mut key = key_name.clone();
if let Some(prefix_) = filters.get() {
key = prefix_.clone() + &key;
}
folder_click_handler(Some(key.clone()))
}>
{key_name_copy.clone()}
</span>}
.into_view()
} else {
view! { <span>{key_name}</span> }.into_view()
}
};

vec![
Column::default("key".to_string()),
Column::new("key".to_string(), None, expand),
Column::default("schema".to_string()),
Column::default("value".to_string()),
Column::default("function_name".to_string()),
Expand All @@ -129,46 +183,49 @@ pub fn DefaultConfig() -> impl IntoView {
]
});

let handle_close = move || {
selected_config.set(None);
close_drawer("default_config_drawer");
};

view! {
<div class="p-8">
{move || {
let handle_close = move || {
close_drawer("default_config_drawer");
selected_config.set(None);
};
if let Some(selected_config_data) = selected_config.get() {
view! {
<Drawer id="default_config_drawer".to_string() header="Edit Key" handle_close=handle_close>
<DefaultConfigForm
edit=true
config_key=selected_config_data.key
config_value=selected_config_data.value
config_type=selected_config_data.type_
config_pattern=selected_config_data.pattern
function_name=selected_config_data.function_name
handle_submit=move || {
default_config_resource.refetch();
close_drawer("default_config_drawer");
selected_config.set(None);
}
/>
</Drawer>
}
} else {
view! {
<Drawer id="default_config_drawer".to_string() header="Create New Key" handle_close=handle_close>
<DefaultConfigForm handle_submit=move || {
default_config_resource.refetch();
close_drawer("default_config_drawer");
}/>
</Drawer>
}
}
}}

<Suspense fallback=move || {
view! { <p>"Loading (Suspense Fallback)..."</p> }
}>
{move || {
let prefix = filters.get();
if let Some(selected_config_data) = selected_config.get() {
view! {
<Drawer id="default_config_drawer".to_string() header="Edit Key" handle_close=handle_close>
<DefaultConfigForm
edit=true
config_key=selected_config_data.key
config_value=selected_config_data.value
config_type=selected_config_data.type_
config_pattern=selected_config_data.pattern
function_name=selected_config_data.function_name
prefix
handle_submit=move || {
default_config_resource.refetch();
selected_config.set(None);
close_drawer("default_config_drawer");
}
/>
</Drawer>
}
} else {
view! {
<Drawer id="default_config_drawer".to_string() header="Create New Key" handle_close=handle_close>
<DefaultConfigForm prefix handle_submit=move || {
default_config_resource.refetch();
selected_config.set(None);
close_drawer("default_config_drawer");
}/>
</Drawer>
}
}
}}
{move || {
let default_config = default_config_resource.get().unwrap_or(vec![]);
let total_default_config_keys = default_config.len().to_string();
Expand All @@ -184,23 +241,105 @@ pub fn DefaultConfig() -> impl IntoView {
ele_map
})
.collect::<Vec<Map<String, Value>>>();

let mut filtered_rows = table_rows.clone();
let mut groups: HashSet<String> = HashSet::new();

let opt_filtered_rows = filtered_rows.into_iter().map(|mut ele| {
let key = ele.get("key").unwrap().to_owned();

let key_arr = if let Some(prefix) = filters.get() {
key.to_string().split(&prefix).map(str::to_string).collect::<Vec<String>>()
} else {
vec!["".to_string(), key.to_string()]
};

if let Some(filtered_key) = key_arr.get(1) {
let new_key = filtered_key.split(".").map(str::to_string).collect::<Vec<String>>();
if new_key.len() == 1 {
// key
ele.insert("key".to_string(), json!(new_key.get(0).unwrap().replace("\"", "")));
} else {
// folder
let key = new_key.get(0).unwrap().to_owned().replace("\"", "")+".";
if !groups.contains(&key) {
ele.insert("key".to_string(), json!(key));
ele.insert("schema".to_string(), json!("-".to_string()));
ele.insert("value".to_string(), json!("-".to_string()));
ele.insert("function_name".to_string(), json!("-".to_string()));
ele.insert("created_at".to_string(), json!("-".to_string()));
ele.insert("created_by".to_string(), json!("-".to_string()));
groups.insert(key);
} else {
return None;
}
}
Some(ele)
} else {
None
}
}).collect::<Vec<Option<Map<String, Value>>>>();
filtered_rows = opt_filtered_rows.into_iter().filter_map(|ele| ele).collect::<Vec<Map<String, Value>>>();

view! {
<div class="pb-4">
<Stat heading="Config Keys" icon="ri-tools-line" number=total_default_config_keys/>
</div>
<div class="card rounded-lg w-full bg-base-100 shadow">
<div class="card-body">
<div class="flex justify-between">
<h2 class="card-title chat-bubble text-gray-800 dark:text-white bg-white font-mono">
"Default Config"
</h2>
<div class="flex justify-between">{
{move || {
let mut bread_crums = vec![BreadCrums {
key: "Default Config".to_string(),
value: None,
is_link: true
}];
if let Some(prefix) = filters.get() {
let mut prefix_arr = prefix.split(".").map(str::to_string).collect::<Vec<String>>();
if !prefix_arr.is_empty() {
prefix_arr.pop();
}
let mut prefix_str = String::new();
for ele in &prefix_arr {
prefix_str.push_str(&ele);
prefix_str.push('.');
bread_crums.push(BreadCrums {
key: ele.clone(),
value: Some(prefix_str.clone()),
is_link: true,
});
}
}
if let Some(last_crumb) = bread_crums.last_mut() {
last_crumb.is_link = false;
}

bread_crums.iter().enumerate().map(|(index, ele)| {
let value = ele.value.clone();
let is_link = ele.is_link.clone();
let last_index = bread_crums.len() - 1;
view! {
<div class="flex">
<h2 on:click=move |_| {if is_link {
folder_click_handler(value.clone())
}}
class={if ele.is_link {"cursor-pointer text-blue-500 underline underline-offset-2"} else {""}}>
{ele.key.clone()}
</h2>
<h2 class="pl-4 pr-4">{if index < last_index {">"} else {""}}</h2>
</div>
}
}).collect_view()
}}
}</div>
<DrawerBtn drawer_id="default_config_drawer".to_string()>
Create Key <i class="ri-edit-2-line ml-2"></i>
</DrawerBtn>
</div>
<Table
cell_style="min-w-48 font-mono".to_string()
rows=table_rows
rows=filtered_rows
key_column="id".to_string()
columns=table_columns.get()
/>
Expand Down
7 changes: 7 additions & 0 deletions crates/frontend/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -207,3 +207,10 @@ impl DropdownOption for FunctionsName {
self.clone()
}
}

#[derive(Debug, Clone)]
pub struct BreadCrums {
pub key: String,
pub value: Option<String>,
pub is_link: bool,
}

0 comments on commit a45be66

Please sign in to comment.