diff --git a/Cargo.lock b/Cargo.lock index 03630d4..b7c5468 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2037,6 +2037,41 @@ dependencies = [ "uuid", ] +[[package]] +name = "leptos_router" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4f1784486ebf36805dac22faee21e3e610aa64b6662a7386f065eeec27ae8" +dependencies = [ + "any_spawner", + "either_of", + "futures", + "gloo-net", + "js-sys", + "leptos", + "leptos_router_macro", + "once_cell", + "or_poisoned", + "reactive_graph", + "send_wrapper", + "tachys", + "thiserror 2.0.4", + "url", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "leptos_router_macro" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eee7ecef3f1c69b51864190c564e4873d84f200e44efb37934208f9525f02a5f" +dependencies = [ + "proc-macro-error2", + "proc-macro2", + "quote", +] + [[package]] name = "leptos_server" version = "0.7.0" @@ -2534,6 +2569,7 @@ dependencies = [ "futures", "leptos", "leptos-use", + "leptos_router", "opendal", "parquet", "serde", diff --git a/Cargo.toml b/Cargo.toml index d904cfb..4144130 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -43,6 +43,7 @@ leptos-use = { version = "0.14.0", features = [ "use_websocket", ] } codee = { version = "0.2", features = ["msgpack_serde"] } +leptos_router = { version = "0.7.0", features = ["nightly"] } [profile.release] strip = true diff --git a/src/file_reader.rs b/src/file_reader.rs index 50163fd..546b301 100644 --- a/src/file_reader.rs +++ b/src/file_reader.rs @@ -1,6 +1,7 @@ use bytes::Bytes; use leptos::prelude::*; use leptos::wasm_bindgen::{prelude::Closure, JsCast}; +use leptos_router::hooks::query_signal; use opendal::{services::Http, services::S3, Operator}; use web_sys::{js_sys, Url}; @@ -34,25 +35,101 @@ pub fn FileReader( set_file_bytes: WriteSignal>, set_file_name: WriteSignal, ) -> impl IntoView { - let default_url = "https://raw.githubusercontent.com/RobinL/iris_parquet/main/gridwatch/gridwatch_2023-01-08.parquet"; - let (url, set_url) = signal(default_url.to_string()); - let (active_tab, set_active_tab) = signal("file".to_string()); + let (active_tab, set_active_tab) = query_signal::("tab"); + + let (url_query, set_url_query) = query_signal::("url"); + let default_url = { + if let Some(url) = url_query.get() { + url + } else { + "https://raw.githubusercontent.com/RobinL/iris_parquet/main/gridwatch/gridwatch_2023-01-08.parquet".to_string() + } + }; + let (url, set_url) = signal(default_url); + let (s3_endpoint, _) = signal(get_stored_value( S3_ENDPOINT_KEY, "https://s3.amazonaws.com", )); let (s3_access_key_id, _) = signal(get_stored_value(S3_ACCESS_KEY_ID_KEY, "")); let (s3_secret_key, _) = signal(get_stored_value(S3_SECRET_KEY_KEY, "")); - let (s3_bucket, set_s3_bucket) = signal(get_stored_value(S3_BUCKET_KEY, "")); - let (s3_region, set_s3_region) = signal(get_stored_value(S3_REGION_KEY, "us-east-1")); - let (s3_file_path, set_s3_file_path) = signal(get_stored_value(S3_FILE_PATH_KEY, "")); + + let (s3_bucket_query, set_s3_bucket_query) = query_signal::("bucket"); + let default_bucket = { + if let Some(bucket) = s3_bucket_query.get() { + bucket + } else { + get_stored_value(S3_BUCKET_KEY, "") + } + }; + let (s3_bucket, set_s3_bucket) = signal(default_bucket); + + let (s3_region_query, set_s3_region_query) = query_signal::("region"); + let default_region = { + if let Some(region) = s3_region_query.get() { + region + } else { + get_stored_value(S3_REGION_KEY, "us-east-1") + } + }; + let (s3_region, set_s3_region) = signal(default_region); + + let (s3_file_path_query, set_s3_file_path_query) = query_signal::("file_path"); + let default_file_path = { + if let Some(file_path) = s3_file_path_query.get() { + file_path + } else { + get_stored_value(S3_FILE_PATH_KEY, "") + } + }; + let (s3_file_path, set_s3_file_path) = signal(default_file_path); + let (is_folded, set_is_folded) = signal(false); - let set_active_tab = move |tab: &str| { - if active_tab.get() == tab { - set_is_folded.set(!is_folded.get()); + Effect::watch( + url, + move |url, _, _| { + let Some(active_tab) = active_tab.get() else { + return; + }; + if active_tab == "url" { + set_url_query.set(Some(url.clone())); + } + }, + true, + ); + + let set_active_tab_fn = move |tab: &str| { + match tab { + "file" => { + set_url_query.set(None); + set_s3_bucket_query.set(None); + set_s3_region_query.set(None); + set_s3_file_path_query.set(None); + } + "url" => { + set_url_query.set(Some(url.get())); + set_s3_bucket_query.set(None); + set_s3_region_query.set(None); + set_s3_file_path_query.set(None); + } + "s3" => { + set_url_query.set(None); + set_s3_bucket_query.set(Some(s3_bucket.get())); + set_s3_region_query.set(Some(s3_region.get())); + set_s3_file_path_query.set(Some(s3_file_path.get())); + } + _ => {} + } + if let Some(active_t) = active_tab.get() { + if active_t == tab { + set_is_folded.set(!is_folded.get()); + } else { + set_active_tab.set(Some(tab.to_string())); + set_is_folded.set(false); + } } else { - set_active_tab.set(tab.to_string()); + set_active_tab.set(Some(tab.to_string())); set_is_folded.set(false); } }; @@ -85,8 +162,7 @@ pub fn FileReader( set_file_name.set(table_name); }; - let on_url_submit = move |ev: web_sys::SubmitEvent| { - ev.prevent_default(); + let on_url_submit = move || { let url_str = url.get(); set_error_message.set(None); @@ -128,8 +204,7 @@ pub fn FileReader( }); }; - let on_s3_submit = move |ev: web_sys::SubmitEvent| { - ev.prevent_default(); + let on_s3_submit = move || { set_error_message.set(None); let endpoint = s3_endpoint.get(); @@ -181,6 +256,15 @@ pub fn FileReader( }); }; + match active_tab.get() { + Some(tab) => match tab.as_str() { + "url" => on_url_submit(), + "s3" => on_s3_submit(), + _ => {} + }, + None => set_active_tab_fn("file"), + } + let on_s3_bucket_change = move |ev| { let value = event_target_value(&ev); save_to_storage(S3_BUCKET_KEY, &value); @@ -206,48 +290,51 @@ pub fn FileReader( @@ -260,8 +347,13 @@ pub fn FileReader( } else { "max-h-[500px] overflow-hidden transition-all duration-300 ease-in-out p-6" }; - match active_tab.get().as_str() { + let active_tab = active_tab.get(); + let Some(active_tab) = active_tab else { + return ().into_any(); + }; + match active_tab.as_str() { "file" => { + view! {
@@ -290,7 +382,13 @@ pub fn FileReader( view! {
-
+
{ view! {
- +