fix(db): fix property and item deletion
This commit is contained in:
parent
0a05b41ffa
commit
a47d6b2e3a
4 changed files with 118 additions and 76 deletions
26
src/api.rs
26
src/api.rs
|
@ -74,15 +74,16 @@ pub async fn create_item(
|
|||
#[cfg(feature = "ssr")]
|
||||
pub async fn delete_item(
|
||||
db: web::Data<Arc<Mutex<Database>>>,
|
||||
url: web::Query<String>,
|
||||
item_id: web::Path<String>,
|
||||
path: web::Path<(String, String)>, // (url, item_id)
|
||||
) -> HttpResponse {
|
||||
let (url, item_id) = path.into_inner();
|
||||
log!("[API] Deleting item {} from URL {}", item_id, url);
|
||||
let db = db.lock().await;
|
||||
match db.delete_item_by_url(&url, &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")
|
||||
Ok(_) => HttpResponse::Ok().finish(),
|
||||
Err(e) => {
|
||||
log!("[API] Delete error: {:?}", e);
|
||||
HttpResponse::InternalServerError().body(e.to_string())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -90,15 +91,16 @@ pub async fn delete_item(
|
|||
#[cfg(feature = "ssr")]
|
||||
pub async fn delete_property(
|
||||
db: web::Data<Arc<Mutex<Database>>>,
|
||||
url: web::Query<String>,
|
||||
property: web::Path<String>,
|
||||
path: web::Path<(String, String)>, // (url, property)
|
||||
) -> HttpResponse {
|
||||
let (url, property) = path.into_inner();
|
||||
log!("[API] Deleting property {} from URL {}", property, url);
|
||||
let db = db.lock().await;
|
||||
match db.delete_property_by_url(&url, &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")
|
||||
Ok(_) => HttpResponse::Ok().finish(),
|
||||
Err(e) => {
|
||||
log!("[API] Delete error: {:?}", e);
|
||||
HttpResponse::InternalServerError().body(e.to_string())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -223,57 +223,75 @@ pub fn ItemsList(
|
|||
}
|
||||
}
|
||||
|
||||
let current_url_for_remove_item = Rc::clone(¤t_url);
|
||||
// Function to 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))
|
||||
let remove_item = {
|
||||
let set_items = set_items.clone();
|
||||
move |index: usize| {
|
||||
let item_id = items.get()[index].id.clone();
|
||||
let current_url = Rc::clone(¤t_url_for_remove_item);
|
||||
spawn_local(async move {
|
||||
let response = gloo_net::http::Request::delete(
|
||||
&format!("/api/urls/{}/items/{}", encode(¤t_url), 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());
|
||||
|
||||
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),
|
||||
}
|
||||
Err(err) => log!("Failed to delete item: {:?}", err),
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
let current_url_for_remove_property = Rc::clone(¤t_url);
|
||||
// Function to remove a property
|
||||
let remove_property = move |property: String| {
|
||||
spawn_local(async move {
|
||||
let response = gloo_net::http::Request::delete(&format!("/api/properties/{}", property))
|
||||
let remove_property = {
|
||||
let set_custom_properties = set_custom_properties.clone();
|
||||
let set_selected_properties = set_selected_properties.clone();
|
||||
let set_items = set_items.clone();
|
||||
move |property: String| {
|
||||
let current_url = Rc::clone(¤t_url_for_remove_property);
|
||||
spawn_local(async move {
|
||||
let response = gloo_net::http::Request::delete(
|
||||
&format!("/api/urls/{}/properties/{}", encode(¤t_url), 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());
|
||||
|
||||
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),
|
||||
}
|
||||
Err(err) => log!("Failed to delete property: {:?}", err),
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// State to store Wikidata suggestions
|
||||
|
@ -596,9 +614,10 @@ pub fn ItemsList(
|
|||
<tr>
|
||||
<th>{ "Property" }</th>
|
||||
{move || items.get().iter().enumerate().map(|(index, item)| {
|
||||
let remove_item = remove_item.clone();
|
||||
view! {
|
||||
<th>
|
||||
{ item.name.clone() }
|
||||
{item.name.clone()}
|
||||
<button on:click=move |_| remove_item(index)>{ "Delete" }</button>
|
||||
</th>
|
||||
}
|
||||
|
@ -753,7 +772,9 @@ pub fn ItemsList(
|
|||
move || {
|
||||
let update_item = Arc::clone(&update_item_outer);
|
||||
let custom_props = custom_properties.get().clone();
|
||||
let remove_property = remove_property.clone();
|
||||
custom_props.into_iter().map(move |property| {
|
||||
let remove_property_clone = remove_property.clone();
|
||||
let update_item_inner = Arc::clone(&update_item);
|
||||
let normalized_property = property.replace("http://www.wikidata.org/prop/", "");
|
||||
let property_label = property_labels.get().get(&normalized_property).cloned().unwrap_or_else(|| normalized_property.clone());
|
||||
|
@ -765,7 +786,7 @@ pub fn ItemsList(
|
|||
{ property_label }
|
||||
<button class="delete-property" on:click=move |_| {
|
||||
log!("Deleting property: {}", property_clone_for_button);
|
||||
remove_property(property_clone_for_button.clone());
|
||||
remove_property_clone(property_clone_for_button.clone());
|
||||
set_custom_properties.update(|props| {
|
||||
props.retain(|p| p != &property_clone_for_button);
|
||||
});
|
||||
|
|
61
src/db.rs
61
src/db.rs
|
@ -274,7 +274,7 @@ mod db_impl {
|
|||
JOIN properties p ON ip.property_id = p.id
|
||||
WHERE ip.item_id = ?"
|
||||
)?;
|
||||
|
||||
|
||||
let mapped_rows = stmt.query_map([&item.id], |row| {
|
||||
Ok((row.get::<_, String>(0)?, row.get::<_, String>(1)?))
|
||||
})?;
|
||||
|
@ -326,35 +326,54 @@ mod db_impl {
|
|||
|
||||
// Delete an item from the database for a specific URL
|
||||
pub async fn delete_item_by_url(&self, url: &str, item_id: &str) -> Result<(), Error> {
|
||||
let conn = self.conn.lock().await;
|
||||
let url_id: i64 = conn.query_row("SELECT id FROM urls WHERE url = ?", &[url], |row| row.get(0))?;
|
||||
conn.execute("DELETE FROM items WHERE id = ? AND url_id = ?", &[item_id, &url_id.to_string()])?;
|
||||
logging::log!("Item deleted from the database for URL: {}", url);
|
||||
let mut conn = self.conn.lock().await;
|
||||
let tx = conn.transaction()?;
|
||||
|
||||
// Get URL ID
|
||||
let url_id: i64 = tx.query_row(
|
||||
"SELECT id FROM urls WHERE url = ?",
|
||||
[url],
|
||||
|row| row.get(0)
|
||||
)?;
|
||||
|
||||
// Delete item and properties
|
||||
tx.execute(
|
||||
"DELETE FROM items WHERE id = ? AND url_id = ?",
|
||||
[item_id, &url_id.to_string()],
|
||||
)?;
|
||||
|
||||
tx.commit()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Delete a property from the database for a specific URL
|
||||
pub async fn delete_property_by_url(&self, url: &str, property: &str) -> Result<(), Error> {
|
||||
let conn = self.conn.lock().await;
|
||||
let url_id: i64 = conn.query_row("SELECT id FROM urls WHERE url = ?", &[url], |row| row.get(0))?;
|
||||
let mut conn = self.conn.lock().await;
|
||||
let tx = conn.transaction()?;
|
||||
|
||||
// Delete from junction table instead of JSON
|
||||
conn.execute(
|
||||
"DELETE FROM item_properties
|
||||
WHERE property_id IN (
|
||||
SELECT id FROM properties WHERE name = ?
|
||||
) AND item_id IN (
|
||||
SELECT id FROM items WHERE url_id = ?
|
||||
)",
|
||||
rusqlite::params![
|
||||
property, // &str
|
||||
url_id // i64
|
||||
],
|
||||
// Get URL ID
|
||||
let url_id: i64 = tx.query_row(
|
||||
"SELECT id FROM urls WHERE url = ?",
|
||||
[url],
|
||||
|row| row.get(0)
|
||||
)?;
|
||||
|
||||
logging::log!("Property deleted from the database for URL: {}", url);
|
||||
|
||||
// Delete property from all items in this URL
|
||||
tx.execute(
|
||||
"DELETE FROM item_properties
|
||||
WHERE property_id IN (
|
||||
SELECT id FROM properties WHERE name = ?
|
||||
)
|
||||
AND item_id IN (
|
||||
SELECT id FROM items WHERE url_id = ?
|
||||
)",
|
||||
[property, &url_id.to_string()],
|
||||
)?;
|
||||
|
||||
tx.commit()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// function to log database state
|
||||
pub async fn debug_dump(&self) -> Result<(), Error> {
|
||||
let conn = self.conn.lock().await;
|
||||
|
|
|
@ -49,9 +49,9 @@ async fn main() -> std::io::Result<()> {
|
|||
web::scope("/urls/{url}")
|
||||
.route("/items", web::get().to(get_items_handler)) // GET items by URL
|
||||
.route("/items", web::post().to(create_item_handler)) // Create item for URL
|
||||
.route("/items/{item_id}", web::delete().to(delete_item_handler)) // Delete item
|
||||
.route("/items/{item_id}", web::delete().to(delete_item)) // Delete item for URL
|
||||
.route("/properties/{property}", web::delete().to(delete_property)) // Delete property for URL
|
||||
)
|
||||
.route("/properties/{property}", web::delete().to(delete_property)), // DELETE /api/properties/{property}
|
||||
)
|
||||
// Register server functions
|
||||
.route("/api/{tail:.*}", leptos_actix::handle_server_fns())
|
||||
|
|
Loading…
Add table
Reference in a new issue