feat(db): enable user to delete items and properties from the database.
This commit is contained in:
parent
afa3bd3ece
commit
68b458df5e
4 changed files with 103 additions and 11 deletions
30
src/api.rs
30
src/api.rs
|
@ -33,3 +33,33 @@ pub async fn create_item(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "ssr")]
|
||||||
|
pub async fn delete_item(
|
||||||
|
db: web::Data<Arc<Mutex<Database>>>,
|
||||||
|
item_id: web::Path<String>,
|
||||||
|
) -> HttpResponse {
|
||||||
|
let db = db.lock().await;
|
||||||
|
match db.delete_item(&item_id).await {
|
||||||
|
Ok(_) => HttpResponse::Ok().body("Item deleted"),
|
||||||
|
Err(err) => {
|
||||||
|
leptos::logging::error!("Failed to delete item: {:?}", err);
|
||||||
|
HttpResponse::InternalServerError().body("Failed to delete item")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "ssr")]
|
||||||
|
pub async fn delete_property(
|
||||||
|
db: web::Data<Arc<Mutex<Database>>>,
|
||||||
|
property: web::Path<String>,
|
||||||
|
) -> HttpResponse {
|
||||||
|
let db = db.lock().await;
|
||||||
|
match db.delete_property(&property).await {
|
||||||
|
Ok(_) => HttpResponse::Ok().body("Property deleted"),
|
||||||
|
Err(err) => {
|
||||||
|
leptos::logging::error!("Failed to delete property: {:?}", err);
|
||||||
|
HttpResponse::InternalServerError().body("Failed to delete property")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -203,6 +203,58 @@ pub fn ItemsList(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// remove an item
|
||||||
|
let remove_item = move |index: usize| {
|
||||||
|
let item_id = items.get()[index].id.clone();
|
||||||
|
spawn_local(async move {
|
||||||
|
let response = gloo_net::http::Request::delete(&format!("/api/items/{}", item_id))
|
||||||
|
.send()
|
||||||
|
.await;
|
||||||
|
match response {
|
||||||
|
Ok(resp) => {
|
||||||
|
if resp.status() == 200 {
|
||||||
|
set_items.update(|items| {
|
||||||
|
items.remove(index);
|
||||||
|
});
|
||||||
|
log!("Item deleted: {}", item_id);
|
||||||
|
} else {
|
||||||
|
log!("Failed to delete item: {}", resp.status_text());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(err) => log!("Failed to delete item: {:?}", err),
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
let remove_property = move |property: String| {
|
||||||
|
spawn_local(async move {
|
||||||
|
let response = gloo_net::http::Request::delete(&format!("/api/properties/{}", property))
|
||||||
|
.send()
|
||||||
|
.await;
|
||||||
|
match response {
|
||||||
|
Ok(resp) => {
|
||||||
|
if resp.status() == 200 {
|
||||||
|
set_custom_properties.update(|props| {
|
||||||
|
props.retain(|p| p != &property);
|
||||||
|
});
|
||||||
|
set_selected_properties.update(|selected| {
|
||||||
|
selected.remove(&property);
|
||||||
|
});
|
||||||
|
set_items.update(|items| {
|
||||||
|
for item in items {
|
||||||
|
item.custom_properties.remove(&property);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
log!("Property deleted: {}", property);
|
||||||
|
} else {
|
||||||
|
log!("Failed to delete property: {}", resp.status_text());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(err) => log!("Failed to delete property: {:?}", err),
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
let (wikidata_suggestions, set_wikidata_suggestions) = create_signal(HashMap::<String, Vec<WikidataSuggestion>>::new());
|
let (wikidata_suggestions, set_wikidata_suggestions) = create_signal(HashMap::<String, Vec<WikidataSuggestion>>::new());
|
||||||
|
|
||||||
// Fetch Wikidata suggestions
|
// Fetch Wikidata suggestions
|
||||||
|
@ -432,14 +484,6 @@ pub fn ItemsList(
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// Remove an item
|
|
||||||
let remove_item = move |index: usize| {
|
|
||||||
set_items.update(|items| {
|
|
||||||
items.remove(index);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// List of properties to display as rows
|
// List of properties to display as rows
|
||||||
let properties = vec!["Name", "Description", "Actions"];
|
let properties = vec!["Name", "Description", "Actions"];
|
||||||
|
|
||||||
|
@ -616,6 +660,7 @@ pub fn ItemsList(
|
||||||
{ property_label }
|
{ property_label }
|
||||||
<button class="delete-property" on:click=move |_| {
|
<button class="delete-property" on:click=move |_| {
|
||||||
log!("Deleting property: {}", property_clone_for_button);
|
log!("Deleting property: {}", property_clone_for_button);
|
||||||
|
remove_property(property_clone_for_button.clone());
|
||||||
set_custom_properties.update(|props| {
|
set_custom_properties.update(|props| {
|
||||||
props.retain(|p| p != &property_clone_for_button);
|
props.retain(|p| p != &property_clone_for_button);
|
||||||
});
|
});
|
||||||
|
|
15
src/db.rs
15
src/db.rs
|
@ -62,6 +62,21 @@ mod db_impl {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn delete_item(&self, item_id: &str) -> Result<(), Error> {
|
||||||
|
let conn = self.conn.lock().await;
|
||||||
|
conn.execute("DELETE FROM items WHERE id = ?", &[item_id])?;
|
||||||
|
logging::log!("Item deleted: {}", item_id);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn delete_property(&self, property: &str) -> Result<(), Error> {
|
||||||
|
let conn = self.conn.lock().await;
|
||||||
|
let query = format!("UPDATE items SET custom_properties = json_remove(custom_properties, '$.{}')", property);
|
||||||
|
conn.execute(&query, []).map_err(|e| Error::from(e))?;
|
||||||
|
logging::log!("Property deleted: {}", property);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
// Retrieve all items from the database
|
// Retrieve all items from the database
|
||||||
pub async fn get_items(&self) -> Result<Vec<DbItem>, Error> {
|
pub async fn get_items(&self) -> Result<Vec<DbItem>, Error> {
|
||||||
let conn = self.conn.lock().await;
|
let conn = self.conn.lock().await;
|
||||||
|
|
|
@ -7,7 +7,7 @@ async fn main() -> std::io::Result<()> {
|
||||||
use leptos_actix::{generate_route_list, LeptosRoutes};
|
use leptos_actix::{generate_route_list, LeptosRoutes};
|
||||||
use compareware::app::*;
|
use compareware::app::*;
|
||||||
use compareware::db::{Database, DbItem};
|
use compareware::db::{Database, DbItem};
|
||||||
use compareware::api::{get_items, create_item}; // Import API handlers
|
use compareware::api::{get_items, create_item, delete_item, delete_property}; // Import API handlers
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use tokio::sync::Mutex;
|
use tokio::sync::Mutex;
|
||||||
|
|
||||||
|
@ -35,8 +35,10 @@ async fn main() -> std::io::Result<()> {
|
||||||
// Register custom API routes BEFORE Leptos server functions
|
// Register custom API routes BEFORE Leptos server functions
|
||||||
.service(
|
.service(
|
||||||
web::scope("/api")
|
web::scope("/api")
|
||||||
.route("/items", web::get().to(get_items))
|
.route("/items", web::get().to(get_items)) // GET /api/items
|
||||||
.route("/items", web::post().to(create_item)),
|
.route("/items", web::post().to(create_item)) // POST /api/items
|
||||||
|
.route("/items/{id}", web::delete().to(delete_item)) // DELETE /api/items/{id}
|
||||||
|
.route("/properties/{property}", web::delete().to(delete_property)), // DELETE /api/properties/{property}
|
||||||
)
|
)
|
||||||
// Register server functions
|
// Register server functions
|
||||||
.route("/api/{tail:.*}", leptos_actix::handle_server_fns())
|
.route("/api/{tail:.*}", leptos_actix::handle_server_fns())
|
||||||
|
|
Loading…
Add table
Reference in a new issue