Compare commits

...

3 commits

4 changed files with 143 additions and 17 deletions

View file

@ -8,9 +8,12 @@ use std::sync::Arc;
use tokio::sync::Mutex;
#[cfg(feature = "ssr")]
pub async fn get_items(db: web::Data<Arc<Mutex<Database>>>) -> HttpResponse {
pub async fn get_items(
db: web::Data<Arc<Mutex<Database>>>,
url: web::Query<String>,
) -> HttpResponse {
let db = db.lock().await;
match db.get_items().await {
match db.get_items_by_url(&url).await {
Ok(items) => HttpResponse::Ok().json(items),
Err(err) => {
leptos::logging::error!("Failed to fetch items: {:?}", err);
@ -22,10 +25,11 @@ pub async fn get_items(db: web::Data<Arc<Mutex<Database>>>) -> HttpResponse {
#[cfg(feature = "ssr")]
pub async fn create_item(
db: web::Data<Arc<Mutex<Database>>>,
url: web::Query<String>,
item: web::Json<DbItem>,
) -> HttpResponse {
let db = db.lock().await;
match db.insert_item(&item.into_inner()).await {
match db.insert_item_by_url(&url, &item.into_inner()).await {
Ok(_) => HttpResponse::Ok().body("Item inserted"),
Err(err) => {
leptos::logging::error!("Failed to insert item: {:?}", err);
@ -37,10 +41,11 @@ 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>,
) -> HttpResponse {
let db = db.lock().await;
match db.delete_item(&item_id).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);
@ -52,14 +57,78 @@ 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>,
) -> HttpResponse {
let db = db.lock().await;
match db.delete_property(&property).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")
}
}
}
#[cfg(feature = "ssr")]
pub async fn get_items_by_url(
db: web::Data<Arc<Mutex<Database>>>,
url: web::Path<String>,
) -> HttpResponse {
let db = db.lock().await;
match db.get_items_by_url(&url).await {
Ok(items) => HttpResponse::Ok().json(items),
Err(err) => {
leptos::logging::error!("Failed to fetch items by URL: {:?}", err);
HttpResponse::InternalServerError().body("Failed to fetch items by URL")
}
}
}
#[cfg(feature = "ssr")]
pub async fn create_item_by_url(
db: web::Data<Arc<Mutex<Database>>>,
url: web::Path<String>,
item: web::Json<DbItem>,
) -> HttpResponse {
let db = db.lock().await;
match db.insert_item_by_url(&url, &item.into_inner()).await {
Ok(_) => HttpResponse::Ok().body("Item inserted"),
Err(err) => {
leptos::logging::error!("Failed to insert item by URL: {:?}", err);
HttpResponse::InternalServerError().body("Failed to insert item by URL")
}
}
}
#[cfg(feature = "ssr")]
pub async fn delete_item_by_url(
db: web::Data<Arc<Mutex<Database>>>,
url: web::Path<String>,
item_id: web::Path<String>,
) -> HttpResponse {
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 by URL: {:?}", err);
HttpResponse::InternalServerError().body("Failed to delete item by URL")
}
}
}
#[cfg(feature = "ssr")]
pub async fn delete_property_by_url(
db: web::Data<Arc<Mutex<Database>>>,
url: web::Path<String>,
property: web::Path<String>,
) -> HttpResponse {
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 by URL: {:?}", err);
HttpResponse::InternalServerError().body("Failed to delete property by URL")
}
}
}

View file

@ -116,7 +116,6 @@ pub fn ItemsList(
id: Uuid::new_v4().to_string(),
name: String::new(),
description: String::new(),
// reviews: vec![],
wikidata_id: None,
custom_properties: HashMap::new(),
}]);
@ -206,7 +205,7 @@ pub fn ItemsList(
name: db_item.name,
description: db_item.description,
wikidata_id: db_item.wikidata_id,
custom_properties, // Deserialized HashMap
custom_properties,
}
})
.collect();

View file

@ -48,13 +48,22 @@ mod db_impl {
Ok(())
}
// Insert a new URL into the database
pub async fn insert_url(&self, url: &str) -> Result<i64, Error> {
let conn = self.conn.lock().await;
let mut stmt = conn.prepare("INSERT INTO urls (url) VALUES (?)")?;
let url_id = stmt.insert(&[url])?;
logging::log!("URL inserted: {}", url);
Ok(url_id)
}
// Insert a new item into the database
pub async fn insert_item(&self, item: &DbItem) -> Result<(), Error> {
pub async fn insert_item(&self, url_id: i64, item: &DbItem) -> Result<(), Error> {
let conn = self.conn.lock().await;
let wikidata_id = item.wikidata_id.as_ref().map(|s| s.as_str()).unwrap_or("");
conn.execute(
"INSERT INTO items (id, name, description, wikidata_id, custom_properties)
VALUES (?, ?, ?, ?, ?)
"INSERT INTO items (id, name, description, wikidata_id, custom_properties, url_id)
VALUES (?, ?, ?, ?, ?, ?)
ON CONFLICT(id) DO UPDATE SET
name = excluded.name,
description = excluded.description,
@ -66,6 +75,7 @@ mod db_impl {
&item.description,
&wikidata_id.to_string(),
&item.custom_properties,
&url_id.to_string(),
],
)?;
logging::log!("Item inserted: {}", item.id);
@ -107,6 +117,61 @@ mod db_impl {
logging::log!("Fetched {} items from the database", result.len()); // Log with Leptos
Ok(result)
}
// Retrieve all items from the database for a specific URL
pub async fn get_items_by_url(&self, url: &str) -> Result<Vec<DbItem>, 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 stmt = conn.prepare("SELECT * FROM items WHERE url_id = ?")?;
let items = stmt.query_map(&[&url_id], |row| {
Ok(DbItem {
id: row.get(0)?,
name: row.get(1)?,
description: row.get(2)?,
wikidata_id: row.get(3)?,
custom_properties: row.get(4)?,
})
})?;
let mut result = Vec::new();
for item in items {
result.push(item?);
}
logging::log!("Fetched {} items from the database for URL: {}", result.len(), url);
Ok(result)
}
// Insert a new item into the database for a specific URL
pub async fn insert_item_by_url(&self, url: &str, item: &DbItem) -> 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))?;
if url_id == 0 {
let url_id = self.insert_url(url).await?;
self.insert_item(url_id, item).await?;
} else {
self.insert_item(url_id, item).await?;
}
logging::log!("Item inserted into the database for URL: {}", url);
Ok(())
}
// 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);
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 query = format!("UPDATE items SET custom_properties = json_remove(custom_properties, '$.{}') WHERE url_id = ?", property);
conn.execute(&query, &[&url_id.to_string()])?;
logging::log!("Property deleted from the database for URL: {}", url);
Ok(())
}
}
// Define a struct to represent an item in the database

View file

@ -7,13 +7,6 @@ pub struct Item {
pub id: String,
pub name: String,
pub description: String,
// pub reviews: Vec<ReviewWithRating>,
pub wikidata_id: Option<String>,
pub custom_properties: HashMap<String, String>,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct ReviewWithRating {
pub content: String,
pub rating: u8, // Ratings from 1 to 5
}