From 3e20ca788d67a8ef1183ff8dfe09aac8ea6321ef Mon Sep 17 00:00:00 2001 From: Shubhranshu Sanjeev Date: Wed, 25 Sep 2024 22:58:48 +0530 Subject: [PATCH 1/3] fix: moved forms to pages and added breadcrumbs for navigation --- .../src/api/default_config/handlers.rs | 13 + .../src/api/dimension/handlers.rs | 27 ++ .../src/api/type_templates/handlers.rs | 15 + .../src/api/experiments/handlers.rs | 6 +- .../src/api/experiments/types.rs | 13 - crates/frontend/src/api.rs | 98 ++++- crates/frontend/src/app.rs | 204 +--------- crates/frontend/src/components.rs | 1 + crates/frontend/src/components/button.rs | 6 +- .../frontend/src/components/context_card.rs | 36 +- .../frontend/src/components/context_form.rs | 168 ++++---- .../components/contextual_override_form.rs | 148 +++++++ .../src/components/default_config_form.rs | 20 +- .../frontend/src/components/dimension_form.rs | 36 +- crates/frontend/src/components/drawer.rs | 2 +- crates/frontend/src/components/dropdown.rs | 18 +- .../components/experiment_conclude_form.rs | 8 +- .../src/components/experiment_form.rs | 185 ++++----- .../src/components/experiment_form/utils.rs | 6 +- .../src/components/experiment_ramp_form.rs | 14 +- .../frontend/src/components/function_form.rs | 16 +- crates/frontend/src/components/input.rs | 24 +- .../frontend/src/components/monaco_editor.rs | 3 +- crates/frontend/src/components/nav_item.rs | 9 +- .../frontend/src/components/override_form.rs | 178 ++++----- crates/frontend/src/components/side_nav.rs | 129 ++----- crates/frontend/src/components/stat.rs | 2 +- crates/frontend/src/components/table.rs | 16 +- crates/frontend/src/components/toast.rs | 2 +- .../src/components/type_template_form.rs | 32 +- .../frontend/src/components/variant_form.rs | 23 +- crates/frontend/src/hoc.rs | 1 + crates/frontend/src/hoc/layout.rs | 171 ++++++--- crates/frontend/src/hoc/nav_breadcrums.rs | 363 ++++++++++++++++++ crates/frontend/src/lib.rs | 1 + crates/frontend/src/pages.rs | 11 +- crates/frontend/src/pages/config_version.rs | 86 +++-- .../frontend/src/pages/config_version_list.rs | 122 +++--- crates/frontend/src/pages/context_override.rs | 336 +++++----------- crates/frontend/src/pages/custom_types.rs | 205 ---------- crates/frontend/src/pages/default_config.rs | 308 ++++++--------- crates/frontend/src/pages/dimensions.rs | 218 ++++------- crates/frontend/src/pages/experiment.rs | 77 ++-- crates/frontend/src/pages/experiment_list.rs | 237 +++++------- crates/frontend/src/pages/function.rs | 14 +- .../src/pages/function/function_create.rs | 8 +- .../src/pages/function/function_list.rs | 155 ++++---- crates/frontend/src/pages/home.rs | 69 ++-- .../src/pages/new_contextual_override.rs | 127 ++++++ .../frontend/src/pages/new_default_config.rs | 21 + crates/frontend/src/pages/new_dimension.rs | 13 + crates/frontend/src/pages/new_experiment.rs | 103 +++++ .../frontend/src/pages/new_template_type.rs | 13 + crates/frontend/src/pages/template_types.rs | 138 +++++++ .../src/pages/update_contextual_override.rs | 121 ++++++ .../src/pages/update_default_config.rs | 59 +++ crates/frontend/src/pages/update_dimension.rs | 52 +++ .../src/pages/update_template_type.rs | 72 ++++ crates/frontend/src/routes.rs | 316 +++++++++++++++ crates/frontend/src/types.rs | 4 +- crates/frontend/tailwind.config.js | 8 + .../src/database/models/cac.rs | 4 +- 62 files changed, 2866 insertions(+), 2025 deletions(-) create mode 100644 crates/frontend/src/components/contextual_override_form.rs create mode 100644 crates/frontend/src/hoc/nav_breadcrums.rs delete mode 100644 crates/frontend/src/pages/custom_types.rs create mode 100644 crates/frontend/src/pages/new_contextual_override.rs create mode 100644 crates/frontend/src/pages/new_default_config.rs create mode 100644 crates/frontend/src/pages/new_dimension.rs create mode 100644 crates/frontend/src/pages/new_experiment.rs create mode 100644 crates/frontend/src/pages/new_template_type.rs create mode 100644 crates/frontend/src/pages/template_types.rs create mode 100644 crates/frontend/src/pages/update_contextual_override.rs create mode 100644 crates/frontend/src/pages/update_default_config.rs create mode 100644 crates/frontend/src/pages/update_dimension.rs create mode 100644 crates/frontend/src/pages/update_template_type.rs create mode 100644 crates/frontend/src/routes.rs diff --git a/crates/context_aware_config/src/api/default_config/handlers.rs b/crates/context_aware_config/src/api/default_config/handlers.rs index 07b7788e8..b36ac2cba 100644 --- a/crates/context_aware_config/src/api/default_config/handlers.rs +++ b/crates/context_aware_config/src/api/default_config/handlers.rs @@ -44,6 +44,7 @@ pub fn endpoints() -> Scope { .service(update_default_config) .service(get) .service(delete) + .service(get_by_name) } #[post("")] @@ -315,6 +316,18 @@ fn fetch_default_key( Ok(res) } +#[get("/{key}")] +async fn get_by_name( + db_conn: DbConnection, + path: Path, + schema_name: SchemaName, +) -> superposition::Result> { + let DbConnection(mut conn) = db_conn; + let key: String = path.into_inner().into(); + let data = fetch_default_key(&key, &mut conn, &schema_name)?; + Ok(Json(data)) +} + #[get("")] async fn get( db_conn: DbConnection, diff --git a/crates/context_aware_config/src/api/dimension/handlers.rs b/crates/context_aware_config/src/api/dimension/handlers.rs index 44bd5634d..d77825913 100644 --- a/crates/context_aware_config/src/api/dimension/handlers.rs +++ b/crates/context_aware_config/src/api/dimension/handlers.rs @@ -36,6 +36,7 @@ pub fn endpoints() -> Scope { .service(create) .service(update) .service(get) + .service(get_by_name) .service(delete_dimension) } @@ -308,6 +309,32 @@ async fn get( })) } +#[get("/{name}")] +async fn get_by_name( + db_conn: DbConnection, + path: Path, + schema_name: SchemaName, +) -> superposition::Result { + use superposition_types::database::{ + models::cac::Dimension, + schema::dimensions::{self, dsl}, + }; + let DbConnection(mut conn) = db_conn; + let name: String = path.into_inner().into(); + let res = dsl::dimensions + .filter(dimensions::dimension.eq(name)) + .select(Dimension::as_select()) + .get_result(&mut conn)?; + + let workspace_settings = get_workspace(&schema_name, &mut conn)?; + + let mandatory_dimensions = + workspace_settings.mandatory_dimensions.unwrap_or_default(); + let is_mandatory = mandatory_dimensions.contains(&res.dimension); + + Ok(HttpResponse::Ok().json(DimensionWithMandatory::new(res, is_mandatory))) +} + #[delete("/{name}")] async fn delete_dimension( path: Path, diff --git a/crates/context_aware_config/src/api/type_templates/handlers.rs b/crates/context_aware_config/src/api/type_templates/handlers.rs index 26c73b8a2..fb26c28a0 100644 --- a/crates/context_aware_config/src/api/type_templates/handlers.rs +++ b/crates/context_aware_config/src/api/type_templates/handlers.rs @@ -26,6 +26,7 @@ pub fn endpoints() -> Scope { .service(create_type) .service(update_type) .service(delete_type) + .service(get_type) } #[post("")] @@ -200,3 +201,17 @@ async fn list_types( data: custom_types, })) } + +#[get("/{type_name}")] +async fn get_type( + db_conn: DbConnection, + path: Path, +) -> superposition::Result { + let DbConnection(mut conn) = db_conn; + let type_name: String = path.into_inner().into(); + + let custom_type = dsl::type_templates + .find(type_name) + .get_result::(&mut conn)?; + Ok(HttpResponse::Ok().json(custom_type)) +} diff --git a/crates/experimentation_platform/src/api/experiments/handlers.rs b/crates/experimentation_platform/src/api/experiments/handlers.rs index a1144aa2f..f30e07bd7 100644 --- a/crates/experimentation_platform/src/api/experiments/handlers.rs +++ b/crates/experimentation_platform/src/api/experiments/handlers.rs @@ -48,8 +48,8 @@ use super::{ types::{ ApplicableVariantsQuery, AuditQueryFilters, ConcludeExperimentRequest, ContextAction, ContextBulkResponse, ContextMoveReq, ContextPutReq, - ExperimentCreateRequest, ExperimentCreateResponse, ExperimentListFilters, - ExperimentResponse, OverrideKeysUpdateRequest, RampRequest, + ExperimentCreateRequest, ExperimentListFilters, ExperimentResponse, + OverrideKeysUpdateRequest, RampRequest, }, }; use crate::api::experiments::{helpers::construct_header_map, types::ExperimentSortOn}; @@ -309,7 +309,7 @@ async fn create( .get_results(&mut conn)?; let inserted_experiment: Experiment = inserted_experiments.remove(0); - let response = ExperimentCreateResponse::from(inserted_experiment.clone()); + let response = ExperimentResponse::from(inserted_experiment.clone()); if let WebhookConfig::Enabled(experiments_webhook_config) = &tenant_config.experiments_webhook_config { diff --git a/crates/experimentation_platform/src/api/experiments/types.rs b/crates/experimentation_platform/src/api/experiments/types.rs index e572bffb6..1b806c006 100644 --- a/crates/experimentation_platform/src/api/experiments/types.rs +++ b/crates/experimentation_platform/src/api/experiments/types.rs @@ -18,19 +18,6 @@ pub struct ExperimentCreateRequest { pub change_reason: String, } -#[derive(Serialize)] -pub struct ExperimentCreateResponse { - pub experiment_id: String, -} - -impl From for ExperimentCreateResponse { - fn from(experiment: Experiment) -> Self { - Self { - experiment_id: experiment.id.to_string(), - } - } -} - /********** Experiment Response Type **************/ // Same as models::Experiments but `id` field is String // JS have limitation of 53-bit integers, so on diff --git a/crates/frontend/src/api.rs b/crates/frontend/src/api.rs index 6fef73e96..b5fd0f79f 100644 --- a/crates/frontend/src/api.rs +++ b/crates/frontend/src/api.rs @@ -3,7 +3,9 @@ use superposition_types::{ custom_query::PaginationParams, database::{ models::{ - cac::{ConfigVersion, DefaultConfig, Function, TypeTemplate}, + cac::{ + ConfigVersion, Context, DefaultConfig, Dimension, Function, TypeTemplate, + }, Workspace, }, types::DimensionWithMandatory, @@ -22,8 +24,8 @@ use crate::{ // #[server(GetDimensions, "/fxn", "GetJson")] pub async fn fetch_dimensions( filters: &PaginationParams, - tenant: String, - org_id: String, + tenant: &str, + org_id: &str, ) -> Result, ServerFnError> { let client = reqwest::Client::new(); let host = use_host_server(); @@ -31,7 +33,7 @@ pub async fn fetch_dimensions( let url = format!("{}/dimension?{}", host, filters.to_string()); let response: PaginatedResponse = client .get(url) - .header("x-tenant", &tenant) + .header("x-tenant", tenant) .header("x-org-id", org_id) .send() .await @@ -46,8 +48,8 @@ pub async fn fetch_dimensions( // #[server(GetDefaultConfig, "/fxn", "GetJson")] pub async fn fetch_default_config( filters: &PaginationParams, - tenant: String, - org_id: String, + tenant: &str, + org_id: &str, ) -> Result, ServerFnError> { let client = reqwest::Client::new(); let host = use_host_server(); @@ -90,8 +92,8 @@ pub async fn fetch_snapshots( } pub async fn delete_context( - tenant: String, context_id: String, + tenant: String, org_id: String, ) -> Result<(), ServerFnError> { let client = reqwest::Client::new(); @@ -200,7 +202,7 @@ pub async fn fetch_function( // #[server(GetConfig, "/fxn", "GetJson")] pub async fn fetch_config( - tenant: String, + tenant: &str, version: Option, org_id: String, ) -> Result { @@ -231,9 +233,9 @@ pub async fn fetch_config( // #[server(GetExperiment, "/fxn", "GetJson")] pub async fn fetch_experiment( - exp_id: String, - tenant: String, - org_id: String, + exp_id: &str, + tenant: &str, + org_id: &str, ) -> Result { let client = reqwest::Client::new(); let host = use_host_server(); @@ -352,3 +354,77 @@ pub async fn fetch_workspaces( .map_err(|e| ServerFnError::new(e.to_string()))?; Ok(response) } + +pub async fn fetch_type(tenant: &str, name: &str) -> Result { + let host = use_host_server(); + let url = format!("{host}/types/{name}"); + let err_handler = |e: String| ServerFnError::new(e.to_string()); + let response = request::<()>( + url, + reqwest::Method::GET, + None, + construct_request_headers(&[("x-tenant", &tenant)]).map_err(err_handler)?, + ) + .await + .map_err(err_handler)?; + parse_json_response::(response) + .await + .map_err(err_handler) +} + +pub async fn fetch_context(tenant: &str, id: &str) -> Result { + let host = use_host_server(); + let url = format!("{host}/context/{id}"); + let err_handler = |e: String| ServerFnError::new(e.to_string()); + let response = request::<()>( + url, + reqwest::Method::GET, + None, + construct_request_headers(&[("x-tenant", &tenant)]).map_err(err_handler)?, + ) + .await + .map_err(err_handler)?; + parse_json_response::(response) + .await + .map_err(err_handler) +} + +pub async fn fetch_default_config_key( + tenant: &str, + key: &str, +) -> Result { + let host = use_host_server(); + let url = format!("{host}/default-config/{key}"); + let err_handler = |e: String| ServerFnError::new(e.to_string()); + let response = request::<()>( + url, + reqwest::Method::GET, + None, + construct_request_headers(&[("x-tenant", &tenant)]).map_err(err_handler)?, + ) + .await + .map_err(err_handler)?; + parse_json_response::(response) + .await + .map_err(err_handler) +} + +pub async fn fetch_dimension( + tenant: &str, + name: &str, +) -> Result { + let host = use_host_server(); + let url = format!("{host}/dimension/{name}"); + let err_handler = |e: String| ServerFnError::new(e.to_string()); + let response = request::<()>( + url, + reqwest::Method::GET, + None, + construct_request_headers(&[("x-tenant", &tenant)]).map_err(err_handler)?, + ) + .await + .map_err(err_handler)?; + parse_json_response::(response) + .await + .map_err(err_handler) +} diff --git a/crates/frontend/src/app.rs b/crates/frontend/src/app.rs index 5d39b154c..73570801d 100755 --- a/crates/frontend/src/app.rs +++ b/crates/frontend/src/app.rs @@ -3,20 +3,8 @@ use leptos_meta::*; use leptos_router::*; use serde_json::json; -use crate::hoc::layout::Layout; -use crate::pages::config_version::ConfigVersion; -use crate::pages::config_version_list::ConfigVersionList; -use crate::pages::dimensions::Dimensions; -use crate::pages::experiment_list::ExperimentList; -use crate::pages::function::{ - function_create::CreateFunctionView, function_list::FunctionList, FunctionPage, -}; -use crate::pages::{ - context_override::ContextOverride, custom_types::TypesPage, - default_config::DefaultConfig, experiment::ExperimentPage, home::Home, - organisations::Organisations, workspace::Workspace, -}; use crate::providers::alert_provider::AlertProvider; +use crate::routes::AppRoutes; use crate::types::Envs; #[component] @@ -38,8 +26,8 @@ pub fn app(app_envs: Envs) -> impl IntoView { let js_href = base.to_owned() + "/pkg/frontend.js"; let import_callback = "() => mod.hydrate()"; view! { - - + + impl IntoView { type_="application/wasm" crossorigin="" /> - + - - - - } - } - /> - - - - } - } - /> - - - - - } - } - /> - - - - - } - } - /> - - - - - } - } - /> - - - - - } - } - /> - - - - - } - } - /> - - - - - } - } - /> - - - - - } - } - /> - - - - - } - } - /> - - - - - } - } - /> - - - - - } - } - /> - - - - - } - } - /> - - - - - } - } - /> - - // - // - // - // } - // } - // /> - + diff --git a/crates/frontend/src/components.rs b/crates/frontend/src/components.rs index b3c1e0b18..24497e541 100644 --- a/crates/frontend/src/components.rs +++ b/crates/frontend/src/components.rs @@ -3,6 +3,7 @@ pub mod button; pub mod condition_pills; pub mod context_card; pub mod context_form; +pub mod contextual_override_form; pub mod default_config_form; pub mod delete_modal; pub mod dimension_form; diff --git a/crates/frontend/src/components/button.rs b/crates/frontend/src/components/button.rs index dee46a3c1..9b294218a 100644 --- a/crates/frontend/src/components/button.rs +++ b/crates/frontend/src/components/button.rs @@ -3,13 +3,15 @@ use web_sys::MouseEvent; #[component] pub fn button( - text: String, + #[prop(into)] text: String, on_click: F, #[prop(default = String::new())] class: String, #[prop(default = String::new())] id: String, #[prop(default = false)] loading: bool, ) -> impl IntoView { - let mut button_class = format!("btn-purple font-medium rounded-lg text-sm px-5 py-2.5 text-center me-2 mb-2 {class}"); + let mut button_class = format!( + "btn-purple font-medium rounded-lg text-sm px-5 py-2.5 text-center {class}" + ); if loading { button_class = button_class + "hover:cursor-not-allowed"; } diff --git a/crates/frontend/src/components/context_card.rs b/crates/frontend/src/components/context_card.rs index 7094e1e12..c8304c22e 100644 --- a/crates/frontend/src/components/context_card.rs +++ b/crates/frontend/src/components/context_card.rs @@ -1,4 +1,5 @@ use leptos::*; +use leptos_router::A; use serde_json::{Map, Value}; use superposition_types::Context; @@ -15,14 +16,6 @@ pub fn context_card( context: Context, overrides: Map, #[prop(default = true)] show_actions: bool, - #[prop(default=Callback::new(|_| {}))] handle_edit: Callback< - (Context, Map), - (), - >, - #[prop(default=Callback::new(|_| {}))] handle_clone: Callback< - (Context, Map), - (), - >, #[prop(default=Callback::new(|_| {}))] handle_delete: Callback, ) -> impl IntoView { let conditions: Conditions = (&context).try_into().unwrap_or_default(); @@ -38,10 +31,7 @@ pub fn context_card( }) .collect::>>(); - // 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()), @@ -65,21 +55,13 @@ pub fn context_card(
- - + + + - - + + + @@ -93,8 +75,7 @@ pub fn context_card( let context_id = context_id.get_value(); handle_delete.call(context_id); } - > - + >
@@ -107,7 +88,6 @@ pub fn context_card(
vec![], }; view! { -
-
-