diff --git a/src/api/mod.rs b/src/api/mod.rs new file mode 100644 index 0000000..46433dd --- /dev/null +++ b/src/api/mod.rs @@ -0,0 +1 @@ +pub mod wikidata; \ No newline at end of file diff --git a/src/api/wikidata.rs b/src/api/wikidata.rs new file mode 100644 index 0000000..3fad8c3 --- /dev/null +++ b/src/api/wikidata.rs @@ -0,0 +1,104 @@ +use leptos::*; +use gloo_net::http::Request; +use serde_json::Value; +use std::collections::HashMap; +use leptos::logging::log; + +#[server(FetchWikidataProperties, "/api/fetch_wikidata_properties")] +pub async fn fetch_wikidata_properties(wikidata_id: String) -> Result, ServerFnError> { + let url = format!( + "https://www.wikidata.org/wiki/Special:EntityData/{}.json", + wikidata_id + ); + + log!("Fetching properties from Wikidata: {}", url); + + // Send the HTTP request + let response = match Request::get(&url).send().await { + Ok(response) => response, + Err(err) => { + log!("Error fetching properties: {:?}", err); + return Err(ServerFnError::ServerError("Failed to fetch properties".to_string())); + } + }; + + // Check the response status code + if response.status() != 200 { + log!("Error fetching properties: {}", response.status()); + return Err(ServerFnError::ServerError("Failed to fetch properties".to_string())); + } + + // Parse the response as JSON + let data: Value = match response.json().await { + Ok(data) => data, + Err(err) => { + log!("Error parsing properties response: {:?}", err); + return Err(ServerFnError::ServerError("Failed to parse properties response".to_string())); + } + }; + + log!("Fetched properties: {:?}", data); + + let mut result = HashMap::new(); + if let Some(entities) = data["entities"].as_object() { + if let Some(entity) = entities.get(&wikidata_id) { + if let Some(claims) = entity["claims"].as_object() { + for (property, values) in claims { + if let Some(value) = values[0]["mainsnak"]["datavalue"]["value"].as_str() { + result.insert(property.clone(), value.to_string()); + } else if let Some(value) = values[0]["mainsnak"]["datavalue"]["value"].as_object() { + result.insert(property.clone(), serde_json::to_string(value).unwrap()); + } else if let Some(value) = values[0]["mainsnak"]["datavalue"]["value"].as_f64() { + result.insert(property.clone(), value.to_string()); + } else { + result.insert(property.clone(), "Unsupported data type".to_string()); + } + } + } else { + log!("No claims found for Wikidata ID: {}", wikidata_id); + } + } else { + log!("Entity not found for Wikidata ID: {}", wikidata_id); + } + } else { + log!("No entities found in the response"); + } + + // Fetch labels for each property + let property_ids: Vec = result.keys().cloned().collect(); + let property_labels_url = format!( + "https://www.wikidata.org/w/api.php?action=wbgetentities&ids={}&props=labels&languages=en&format=json", + property_ids.join("|") + ); + + // Send the HTTP request for property labels + let labels_response = match Request::get(&property_labels_url).send().await { + Ok(response) => response, + Err(err) => { + log!("Error fetching property labels: {:?}", err); + return Err(ServerFnError::ServerError("Failed to fetch property labels".to_string())); + } + }; + + // Parse the response as JSON + let labels_data: Value = match labels_response.json().await { + Ok(data) => data, + Err(err) => { + log!("Error parsing property labels response: {:?}", err); + return Err(ServerFnError::ServerError("Failed to parse property labels response".to_string())); + } + }; + + let mut new_result = HashMap::new(); + if let Some(entities) = labels_data["entities"].as_object() { + for (id, entity) in entities { + if let Some(label) = entity["labels"]["en"]["value"].as_str() { + if let Some(value) = result.get(id) { + new_result.insert(label.to_string(), value.clone()); + } + } + } + } + log!("Fetched properties: {:?}", result); // Log the fetched properties + Ok(new_result) +} \ No newline at end of file diff --git a/src/components/items_list.rs b/src/components/items_list.rs index 56ff592..1833915 100644 --- a/src/components/items_list.rs +++ b/src/components/items_list.rs @@ -1,5 +1,6 @@ use crate::components::editable_cell::EditableCell; use crate::components::editable_cell::InputType; +use crate::api::wikidata::fetch_wikidata_properties; use leptos::*; use serde::Deserialize; use uuid::Uuid; @@ -79,45 +80,18 @@ pub fn ItemsList( }; //function to fetch properties - async fn fetch_item_properties(wikidata_id: &str, set_fetched_properties: WriteSignal>) -> HashMap { - let url = format!( - "https://www.wikidata.org/wiki/Special:EntityData/{}.json", - wikidata_id - ); - - match gloo_net::http::Request::get(&url).send().await { - Ok(response) => { - if let Ok(data) = response.json::().await { - if let Some(entities) = data["entities"].as_object() { - if let Some(entity) = entities.get(wikidata_id) { - if let Some(claims) = entity["claims"].as_object() { - let mut result = HashMap::new(); - for (property, values) in claims { - if let Some(value) = values[0]["mainsnak"]["datavalue"]["value"].as_str() { - result.insert(property.clone(), value.to_string()); - } else if let Some(value) = values[0]["mainsnak"]["datavalue"]["value"].as_object() { - result.insert(property.clone(), serde_json::to_string(value).unwrap()); - } else if let Some(value) = values[0]["mainsnak"]["datavalue"]["value"].as_f64() { - result.insert(property.clone(), value.to_string()); - } else { - result.insert(property.clone(), "Unsupported data type".to_string()); - } - } - set_fetched_properties.update(|properties| { - for (key, val) in result.clone() { - properties.insert(key.clone(), val.clone()); - } - }); - return result; - } - } + async fn fetch_item_properties(wikidata_id: &str, set_fetched_properties: WriteSignal>) { + match fetch_wikidata_properties(wikidata_id.to_string()).await { + Ok(properties) => { + log!("Fetched properties for Wikidata ID {}: {:?}",wikidata_id, properties); + set_fetched_properties.update(|props| { + for (key, val) in properties { + props.insert(key, val); } - } + }); } - Err(err) => log!("Error fetching item properties: {:?}", err), + Err(err) => log!("Error fetching properties: {:?}", err), } - - HashMap::new() } diff --git a/src/lib.rs b/src/lib.rs index 10f7ef7..0ccb9ab 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 = "hydrate")]