feat(db): add API endpoint for updating items to db and implement server-side functionality

This commit is contained in:
ryan 2025-01-22 14:14:18 +03:00
parent 5bd19803fe
commit af3f89c561
5 changed files with 95 additions and 28 deletions

46
src/api.rs Normal file
View file

@ -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()))
}
}
}

View file

@ -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<String>,
}
#[derive(Debug, Serialize)]
struct ClientDbItem {
id: String,
name: String,
description: String,
wikidata_id: Option<String>,
custom_properties: String,
}
#[component]
pub fn ItemsList(
items: ReadSignal<Vec<Item>>,
@ -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 {

View file

@ -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,

View file

@ -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;

View file

@ -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);
}
}