From af3f89c561f108554f236f44ac1a468864f4fd41 Mon Sep 17 00:00:00 2001 From: ryan Date: Wed, 22 Jan 2025 14:14:18 +0300 Subject: [PATCH] feat(db): add API endpoint for updating items to db and implement server-side functionality --- src/api.rs | 46 +++++++++++++++++++++++++++++ src/components/items_list.rs | 56 +++++++++++++++++++++--------------- src/db.rs | 2 +- src/lib.rs | 1 + src/main.rs | 18 +++++++++--- 5 files changed, 95 insertions(+), 28 deletions(-) create mode 100644 src/api.rs diff --git a/src/api.rs b/src/api.rs new file mode 100644 index 0000000..bdb08fc --- /dev/null +++ b/src/api.rs @@ -0,0 +1,46 @@ +#[cfg(feature = "ssr")] +use leptos::*; +#[cfg(feature = "ssr")] +use leptos::logging::log; +#[cfg(feature = "ssr")] +use crate::db::{Database, DbItem}; + +#[cfg(feature = "ssr")] +#[server(UpdateItem, "/api")] +pub async fn update_item_db(client_db_item: ClientDbItem) -> Result<(), ServerFnError> { + + let db_item = DbItem { + id: client_db_item.id, + name: client_db_item.name, + description: client_db_item.description, + wikidata_id: client_db_item.wikidata_id, + custom_properties: client_db_item.custom_properties, + }; + + // Log the start of the function + log!("Starting update_item function for item: {:?}", db_item); + + // Open the database + let db = match Database::new("items.db") { + Ok(db) => { + log!("Database opened successfully"); + db + } + Err(e) => { + log!("Failed to open database: {}", e); + return Err(ServerFnError::ServerError(e.to_string())); + } + }; + + // Insert the item into the database + match db.insert_item(&db_item) { + Ok(_) => { + log!("Item inserted successfully: {:?}", db_item); + Ok(()) + } + Err(e) => { + log!("Failed to insert item into database: {}", e); + Err(ServerFnError::ServerError(e.to_string())) + } + } +} \ No newline at end of file diff --git a/src/components/items_list.rs b/src/components/items_list.rs index a649390..8916498 100644 --- a/src/components/items_list.rs +++ b/src/components/items_list.rs @@ -1,13 +1,14 @@ use crate::components::editable_cell::EditableCell; use crate::components::editable_cell::InputType; use leptos::*; -use serde::Deserialize; +use serde::{Deserialize, Serialize}; use uuid::Uuid; use leptos::logging::log; use crate::models::item::Item; use std::collections::HashMap; use std::sync::Arc; use wasm_bindgen::JsCast; +use crate::api::update_item_db; #[cfg(feature = "ssr")] use crate::db::{Database, DbItem}; @@ -19,6 +20,15 @@ struct WikidataSuggestion { description: Option, } +#[derive(Debug, Serialize)] +struct ClientDbItem { + id: String, + name: String, + description: String, + wikidata_id: Option, + custom_properties: String, +} + #[component] pub fn ItemsList( items: ReadSignal>, @@ -247,7 +257,7 @@ pub fn ItemsList( let set_property_labels = set_property_labels.clone(); spawn_local(async move { let properties = fetch_item_properties(&wikidata_id, set_fetched_properties, set_property_labels).await; - // log!("Fetched properties for index {}: {:?}", index, properties); + log!("Fetched properties for index {}: {:?}", index, properties); }); } } @@ -260,28 +270,28 @@ pub fn ItemsList( item.custom_properties.insert(field.to_string(), value.clone()); } } + + // Send the updated item to the server using the API endpoint + let client_db_item = ClientDbItem { + id: item.id.clone(), + name: item.name.clone(), + description: item.description.clone(), + wikidata_id: item.wikidata_id.clone(), + custom_properties: serde_json::to_string(&item.custom_properties).unwrap(), + }; + + + spawn_local(async move { + match update_item_db(client_db_item).await { + Ok(_) => { + log!("Item updated successfully on the server"); + } + Err(e) => { + log!("Error updating item on the server: {}", e); + } + } + }); } - #[cfg(feature = "ssr")] - { - log!("SSR block in update_item is executing"); - // Update items in the database - let db_item = DbItem { - id: items[index].id.clone(), - name: items[index].name.clone(), - description: items[index].description.clone(), - wikidata_id: items[index].wikidata_id.clone(), - custom_properties: serde_json::to_string(&items[index].custom_properties).unwrap(), - }; - let db = Database::new("items.db").expect("Failed to open database"); - match db.insert_item(&db_item) { - Ok(_) => { - log!("Item inserted successfully"); - } - Err(e) => { - log!("Error inserting item: {}", e); - } - } - } // Automatically add a new row when editing the last row if index == items.len() - 1 && !value.is_empty() { items.push(Item { diff --git a/src/db.rs b/src/db.rs index f9124dd..2bf78a5 100644 --- a/src/db.rs +++ b/src/db.rs @@ -61,7 +61,7 @@ mod db_impl { } // Define a struct to represent an item in the database - #[derive(Debug, Deserialize, Serialize)] + #[derive(Debug, Deserialize, Serialize, Clone)] pub struct DbItem { pub id: String, pub name: String, diff --git a/src/lib.rs b/src/lib.rs index 51d66af..a2a7cab 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,6 +2,7 @@ pub mod app; pub mod components; pub mod models; pub mod nostr; +pub mod api; #[cfg(feature = "ssr")] pub mod db; diff --git a/src/main.rs b/src/main.rs index 535b829..2abc297 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,6 @@ +use actix_web::{web, App, HttpServer}; +use compareware::api::update_item_db; // Corrected server function name +use compareware::db::Database; #[cfg(feature = "ssr")] #[actix_web::main] async fn main() -> std::io::Result<()> { @@ -7,24 +10,31 @@ async fn main() -> std::io::Result<()> { use leptos_actix::{generate_route_list, LeptosRoutes}; use compareware::app::*; + // Load configuration let conf = get_configuration(None).await.unwrap(); let addr = conf.leptos_options.site_addr; + // Generate the list of routes in your Leptos App let routes = generate_route_list(App); println!("listening on http://{}", &addr); + // Start the Actix Web server HttpServer::new(move || { let leptos_options = &conf.leptos_options; let site_root = &leptos_options.site_root; App::new() - // serve JS/WASM/CSS from `pkg` + // Register server functions + .route("/api/{tail:.*}", leptos_actix::handle_server_fns()) + // Serve JS/WASM/CSS from `pkg` .service(Files::new("/pkg", format!("{site_root}/pkg"))) - // serve other assets from the `assets` directory + // Serve other assets from the `assets` directory .service(Files::new("/assets", site_root)) - // serve the favicon from /favicon.ico + // Serve the favicon from /favicon.ico .service(favicon) + // Register Leptos routes .leptos_routes(leptos_options.to_owned(), routes.to_owned(), App) + // Pass Leptos options to the app .app_data(web::Data::new(leptos_options.to_owned())) //.wrap(middleware::Compress::default()) }) @@ -63,4 +73,4 @@ pub fn main() { console_error_panic_hook::set_once(); leptos::mount_to_body(App); -} +} \ No newline at end of file