feat(item_list): implement querying using GRAPHQL
This commit is contained in:
parent
af921088f9
commit
23cd674e31
3 changed files with 135 additions and 127 deletions
7
Cargo.lock
generated
7
Cargo.lock
generated
|
@ -785,6 +785,7 @@ dependencies = [
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"thiserror 2.0.9",
|
"thiserror 2.0.9",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
"urlencoding",
|
||||||
"uuid",
|
"uuid",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
"wasm-bindgen-futures",
|
"wasm-bindgen-futures",
|
||||||
|
@ -3400,6 +3401,12 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "urlencoding"
|
||||||
|
version = "2.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "utf-8"
|
name = "utf-8"
|
||||||
version = "0.7.6"
|
version = "0.7.6"
|
||||||
|
|
|
@ -32,6 +32,7 @@ thiserror = "2.0.9"
|
||||||
zerofrom = "0.1"
|
zerofrom = "0.1"
|
||||||
mio = "0.8"
|
mio = "0.8"
|
||||||
chrono = "0.4"
|
chrono = "0.4"
|
||||||
|
urlencoding = "2.1.2"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["ssr"]
|
default = ["ssr"]
|
||||||
|
|
|
@ -9,6 +9,8 @@ use std::collections::HashMap;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use wasm_bindgen::JsCast;
|
use wasm_bindgen::JsCast;
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
|
use gloo_net::http::Request;
|
||||||
|
use serde_json::Value;
|
||||||
|
|
||||||
#[derive(Deserialize, Clone, Debug)]
|
#[derive(Deserialize, Clone, Debug)]
|
||||||
struct WikidataSuggestion {
|
struct WikidataSuggestion {
|
||||||
|
@ -17,7 +19,6 @@ struct WikidataSuggestion {
|
||||||
description: Option<String>,
|
description: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(Deserialize, Debug)]
|
||||||
struct DbItem {
|
struct DbItem {
|
||||||
id: String,
|
id: String,
|
||||||
|
@ -41,15 +42,16 @@ pub fn ItemsList(
|
||||||
// State to manage dynamic property names
|
// State to manage dynamic property names
|
||||||
let (custom_properties, set_custom_properties) = create_signal(Vec::<String>::new());
|
let (custom_properties, set_custom_properties) = create_signal(Vec::<String>::new());
|
||||||
|
|
||||||
// state to manage suggestions visibility
|
// State to manage suggestions visibility
|
||||||
let (show_suggestions, set_show_suggestions) = create_signal(HashMap::<String, bool>::new());
|
let (show_suggestions, set_show_suggestions) = create_signal(HashMap::<String, bool>::new());
|
||||||
|
|
||||||
// cache to store fetched properties
|
// Cache to store fetched properties
|
||||||
let (fetched_properties, set_fetched_properties) = create_signal(HashMap::<String, String>::new());
|
let (fetched_properties, set_fetched_properties) = create_signal(HashMap::<String, String>::new());
|
||||||
|
|
||||||
// Signal to store the fetched property labels
|
// Signal to store the fetched property labels
|
||||||
let (property_labels, set_property_labels) = create_signal(HashMap::<String, String>::new());
|
let (property_labels, set_property_labels) = create_signal(HashMap::<String, String>::new());
|
||||||
|
|
||||||
|
// Load items from the database on component mount
|
||||||
spawn_local(async move {
|
spawn_local(async move {
|
||||||
match load_items_from_db().await {
|
match load_items_from_db().await {
|
||||||
Ok(loaded_items) => {
|
Ok(loaded_items) => {
|
||||||
|
@ -69,7 +71,6 @@ pub fn ItemsList(
|
||||||
|
|
||||||
// Derive selected properties from the loaded items
|
// Derive selected properties from the loaded items
|
||||||
let mut selected_props = HashMap::new();
|
let mut selected_props = HashMap::new();
|
||||||
let loaded_items_clone = loaded_items.clone();
|
|
||||||
for item in loaded_items {
|
for item in loaded_items {
|
||||||
for (property, _) in item.custom_properties {
|
for (property, _) in item.custom_properties {
|
||||||
selected_props.insert(property, true);
|
selected_props.insert(property, true);
|
||||||
|
@ -79,19 +80,17 @@ pub fn ItemsList(
|
||||||
|
|
||||||
// Update the custom_properties signal
|
// Update the custom_properties signal
|
||||||
let mut custom_props = Vec::new();
|
let mut custom_props = Vec::new();
|
||||||
for item in loaded_items_clone {
|
for item in loaded_items {
|
||||||
for (property, _) in &item.custom_properties {
|
for (property, _) in &item.custom_properties {
|
||||||
if !custom_props.iter().any(|p| p == property) {
|
if !custom_props.contains(property) {
|
||||||
custom_props.push(property.clone());
|
custom_props.push(property.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let custom_props_clone = custom_props.clone();
|
|
||||||
set_custom_properties.set(custom_props);
|
set_custom_properties.set(custom_props);
|
||||||
|
|
||||||
// Fetch labels for the custom properties
|
// Fetch labels for the custom properties
|
||||||
let property_ids = custom_props_clone;
|
let property_ids = custom_props.clone();
|
||||||
let labels = fetch_property_labels(property_ids).await;
|
let labels = fetch_property_labels(property_ids).await;
|
||||||
set_property_labels.update(|labels_map| {
|
set_property_labels.update(|labels_map| {
|
||||||
for (key, value) in labels {
|
for (key, value) in labels {
|
||||||
|
@ -107,14 +106,12 @@ pub fn ItemsList(
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
// Ensure there's an initial empty row
|
// Ensure there's an initial empty row
|
||||||
if items.get().is_empty() {
|
if items.get().is_empty() {
|
||||||
set_items.set(vec![Item {
|
set_items.set(vec![Item {
|
||||||
id: Uuid::new_v4().to_string(),
|
id: Uuid::new_v4().to_string(),
|
||||||
name: String::new(),
|
name: String::new(),
|
||||||
description: String::new(),
|
description: String::new(),
|
||||||
// reviews: vec![],
|
|
||||||
wikidata_id: None,
|
wikidata_id: None,
|
||||||
custom_properties: HashMap::new(),
|
custom_properties: HashMap::new(),
|
||||||
}]);
|
}]);
|
||||||
|
@ -124,10 +121,10 @@ pub fn ItemsList(
|
||||||
async fn save_item_to_db(item: Item, selected_properties: ReadSignal<HashMap<String, bool>>) {
|
async fn save_item_to_db(item: Item, selected_properties: ReadSignal<HashMap<String, bool>>) {
|
||||||
// Use a reactive closure to access `selected_properties`
|
// Use a reactive closure to access `selected_properties`
|
||||||
let custom_properties: HashMap<String, String> = (move || {
|
let custom_properties: HashMap<String, String> = (move || {
|
||||||
let selected_props = selected_properties.get(); // Access the signal inside a reactive closure
|
let selected_props = selected_properties.get();
|
||||||
item.custom_properties
|
item.custom_properties
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter(|(key, _)| selected_props.contains_key(key)) // Use the extracted value
|
.filter(|(key, _)| selected_props.contains_key(key))
|
||||||
.collect()
|
.collect()
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
@ -141,7 +138,7 @@ pub fn ItemsList(
|
||||||
name: String,
|
name: String,
|
||||||
description: String,
|
description: String,
|
||||||
wikidata_id: Option<String>,
|
wikidata_id: Option<String>,
|
||||||
custom_properties: String, // JSON-encoded string
|
custom_properties: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
let item_to_send = ItemToSend {
|
let item_to_send = ItemToSend {
|
||||||
|
@ -149,7 +146,7 @@ pub fn ItemsList(
|
||||||
name: item.name,
|
name: item.name,
|
||||||
description: item.description,
|
description: item.description,
|
||||||
wikidata_id: item.wikidata_id,
|
wikidata_id: item.wikidata_id,
|
||||||
custom_properties, // Use the serialized string
|
custom_properties,
|
||||||
};
|
};
|
||||||
|
|
||||||
let response = gloo_net::http::Request::post("/api/items")
|
let response = gloo_net::http::Request::post("/api/items")
|
||||||
|
@ -170,7 +167,7 @@ pub fn ItemsList(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//function to load items from database
|
// Function to load items from the database
|
||||||
async fn load_items_from_db() -> Result<Vec<Item>, String> {
|
async fn load_items_from_db() -> Result<Vec<Item>, String> {
|
||||||
let response = gloo_net::http::Request::get("/api/items")
|
let response = gloo_net::http::Request::get("/api/items")
|
||||||
.send()
|
.send()
|
||||||
|
@ -179,14 +176,11 @@ pub fn ItemsList(
|
||||||
|
|
||||||
if response.status() == 200 {
|
if response.status() == 200 {
|
||||||
// Deserialize into Vec<DbItem>
|
// Deserialize into Vec<DbItem>
|
||||||
log!("Loading items from DB...");
|
|
||||||
let db_items = response
|
let db_items = response
|
||||||
.json::<Vec<DbItem>>()
|
.json::<Vec<DbItem>>()
|
||||||
.await
|
.await
|
||||||
.map_err(|err| format!("Failed to parse items: {:?}", err))?;
|
.map_err(|err| format!("Failed to parse items: {:?}", err))?;
|
||||||
|
|
||||||
log!("Deserialized DB items: {:?}", db_items);
|
|
||||||
|
|
||||||
// Convert DbItem to Item
|
// Convert DbItem to Item
|
||||||
let items = db_items
|
let items = db_items
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
@ -194,28 +188,24 @@ pub fn ItemsList(
|
||||||
// Deserialize `custom_properties` from a JSON string to a HashMap
|
// Deserialize `custom_properties` from a JSON string to a HashMap
|
||||||
let custom_properties: HashMap<String, String> =
|
let custom_properties: HashMap<String, String> =
|
||||||
serde_json::from_str(&db_item.custom_properties)
|
serde_json::from_str(&db_item.custom_properties)
|
||||||
.unwrap_or_default(); // Fallback to an empty HashMap if deserialization fails
|
.unwrap_or_default();
|
||||||
|
|
||||||
log!("Loaded item: {:?}", db_item.id);
|
|
||||||
log!("Custom properties: {:?}", custom_properties);
|
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: db_item.id,
|
id: db_item.id,
|
||||||
name: db_item.name,
|
name: db_item.name,
|
||||||
description: db_item.description,
|
description: db_item.description,
|
||||||
wikidata_id: db_item.wikidata_id,
|
wikidata_id: db_item.wikidata_id,
|
||||||
custom_properties, // Deserialized HashMap
|
custom_properties,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
log!("Converted items: {:?}", items);
|
|
||||||
Ok(items)
|
Ok(items)
|
||||||
} else {
|
} else {
|
||||||
Err(format!("Failed to fetch items: {}", response.status_text()))
|
Err(format!("Failed to fetch items: {}", response.status_text()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove an item
|
// Function to remove an item
|
||||||
let remove_item = move |index: usize| {
|
let remove_item = move |index: usize| {
|
||||||
let item_id = items.get()[index].id.clone();
|
let item_id = items.get()[index].id.clone();
|
||||||
spawn_local(async move {
|
spawn_local(async move {
|
||||||
|
@ -238,6 +228,7 @@ pub fn ItemsList(
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Function to remove a property
|
||||||
let remove_property = move |property: String| {
|
let remove_property = move |property: String| {
|
||||||
spawn_local(async move {
|
spawn_local(async move {
|
||||||
let response = gloo_net::http::Request::delete(&format!("/api/properties/{}", property))
|
let response = gloo_net::http::Request::delete(&format!("/api/properties/{}", property))
|
||||||
|
@ -267,9 +258,10 @@ pub fn ItemsList(
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// State to store Wikidata suggestions
|
||||||
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
|
// Function to fetch Wikidata suggestions
|
||||||
let fetch_wikidata_suggestions = move |key: String, query: String| {
|
let fetch_wikidata_suggestions = move |key: String, query: String| {
|
||||||
log!("Fetching suggestions for key: {}, query: {}", key, query);
|
log!("Fetching suggestions for key: {}, query: {}", key, query);
|
||||||
spawn_local(async move {
|
spawn_local(async move {
|
||||||
|
@ -288,9 +280,7 @@ pub fn ItemsList(
|
||||||
match gloo_net::http::Request::get(&url).send().await {
|
match gloo_net::http::Request::get(&url).send().await {
|
||||||
Ok(response) => {
|
Ok(response) => {
|
||||||
if let Ok(data) = response.json::<WikidataResponse>().await {
|
if let Ok(data) = response.json::<WikidataResponse>().await {
|
||||||
log!("Fetching suggestions for key: {}, query: {}", key, query);
|
|
||||||
set_wikidata_suggestions.update(|suggestions| {
|
set_wikidata_suggestions.update(|suggestions| {
|
||||||
log!("Updated suggestions: {:?}", suggestions);
|
|
||||||
suggestions.insert(key, data.search);
|
suggestions.insert(key, data.search);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -300,13 +290,12 @@ pub fn ItemsList(
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// function to handle different nested JSON types for property values
|
// Function to handle different nested JSON types for property values
|
||||||
async fn parse_property_value(value: &serde_json::Value) -> String {
|
async fn parse_property_value(value: &serde_json::Value) -> String {
|
||||||
match value {
|
match value {
|
||||||
serde_json::Value::String(text) => text.clone(),
|
serde_json::Value::String(text) => text.clone(),
|
||||||
serde_json::Value::Number(num) => num.to_string(),
|
serde_json::Value::Number(num) => num.to_string(),
|
||||||
serde_json::Value::Object(map) => {
|
serde_json::Value::Object(map) => {
|
||||||
|
|
||||||
// Handle time values
|
// Handle time values
|
||||||
if let Some(time_value) = map.get("time") {
|
if let Some(time_value) = map.get("time") {
|
||||||
let precision = map.get("precision").and_then(|p| p.as_u64()).unwrap_or(11);
|
let precision = map.get("precision").and_then(|p| p.as_u64()).unwrap_or(11);
|
||||||
|
@ -326,10 +315,9 @@ pub fn ItemsList(
|
||||||
|
|
||||||
// Handle Wikidata entity references
|
// Handle Wikidata entity references
|
||||||
if let Some(id) = map.get("id") {
|
if let Some(id) = map.get("id") {
|
||||||
// Handle Wikidata entity references
|
|
||||||
let entity_id = id.as_str().unwrap_or("");
|
let entity_id = id.as_str().unwrap_or("");
|
||||||
if entity_id.starts_with("Q") {
|
if entity_id.starts_with("Q") {
|
||||||
return fetch_entity_label(entity_id).await;
|
return fetch_entity_labels(vec![entity_id]).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
serde_json::to_string(map).unwrap_or("Complex Object".to_string())
|
serde_json::to_string(map).unwrap_or("Complex Object".to_string())
|
||||||
|
@ -338,77 +326,82 @@ pub fn ItemsList(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn fetch_entity_label(entity_id: &str) -> String {
|
// Function to fetch labels for multiple Wikidata entities
|
||||||
let url = format!(
|
async fn fetch_entity_labels(entity_ids: Vec<String>) -> Result<Vec<(String, String)>, String> {
|
||||||
"https://www.wikidata.org/w/api.php?action=wbgetentities&ids={}&props=labels&languages=en&format=json&origin=*",
|
let query = format!(
|
||||||
|
"PREFIX wdt: <http://www.wikidata.org/prop/direct/>
|
||||||
|
PREFIX wd: <http://www.wikidata.org/entity/>
|
||||||
|
|
||||||
|
SELECT ?item ?itemLabel
|
||||||
|
WHERE {{
|
||||||
|
VALUES ?item {{ {} }}
|
||||||
|
SERVICE wikibase:label {{
|
||||||
|
bd:serviceParam wikibase:language \"en\".
|
||||||
|
}}
|
||||||
|
}}",
|
||||||
|
entity_ids.join(" ")
|
||||||
|
);
|
||||||
|
|
||||||
|
let url = format!("https://query.wikidata.org/sparql?query={}", query);
|
||||||
|
|
||||||
|
match Request::get(&url).send().await {
|
||||||
|
Ok(response) => {
|
||||||
|
if let Ok(data) = response.json::<Value>().await {
|
||||||
|
let results = data["results"]["bindings"].as_array().unwrap_or(&vec![]).to_vec();
|
||||||
|
let mut labels = Vec::new();
|
||||||
|
for result in results {
|
||||||
|
let item = result["item"]["value"].as_str().unwrap_or("");
|
||||||
|
let label = result["itemLabel"]["value"].as_str().unwrap_or("");
|
||||||
|
labels.push((item.to_string(), label.to_string()));
|
||||||
|
}
|
||||||
|
Ok(labels)
|
||||||
|
} else {
|
||||||
|
Err("Failed to parse response".to_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(err) => Err(format!("Failed to fetch entity labels: {:?}", err)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to fetch properties for a specific Wikidata entity
|
||||||
|
async fn fetch_entity_properties(entity_id: String) -> Result<Vec<(String, String)>, String> {
|
||||||
|
let query = format!(
|
||||||
|
"PREFIX wdt: <http://www.wikidata.org/prop/direct/>
|
||||||
|
PREFIX wd: <http://www.wikidata.org/entity/>
|
||||||
|
|
||||||
|
SELECT ?property ?propertyLabel ?value
|
||||||
|
WHERE {{
|
||||||
|
VALUES ?item {{ wd:{} }}
|
||||||
|
?item ?property ?value.
|
||||||
|
SERVICE wikibase:label {{
|
||||||
|
bd:serviceParam wikibase:language \"en\".
|
||||||
|
}}
|
||||||
|
}}",
|
||||||
entity_id
|
entity_id
|
||||||
);
|
);
|
||||||
|
|
||||||
match gloo_net::http::Request::get(&url).send().await {
|
let url = format!("https://query.wikidata.org/sparql?query={}", query);
|
||||||
|
|
||||||
|
match Request::get(&url).send().await {
|
||||||
Ok(response) => {
|
Ok(response) => {
|
||||||
if let Ok(data) = response.json::<serde_json::Value>().await {
|
if let Ok(data) = response.json::<Value>().await {
|
||||||
if let Some(entity) = data["entities"][entity_id]["labels"]["en"]["value"].as_str() {
|
let results = data["results"]["bindings"].as_array().unwrap_or(&vec![]).to_vec();
|
||||||
return entity.to_string();
|
let mut properties = Vec::new();
|
||||||
|
for result in results {
|
||||||
|
let property = result["property"]["value"].as_str().unwrap_or("");
|
||||||
|
let value = result["value"]["value"].as_str().unwrap_or("");
|
||||||
|
properties.push((property.to_string(), value.to_string()));
|
||||||
|
}
|
||||||
|
Ok(properties)
|
||||||
|
} else {
|
||||||
|
Err("Failed to parse response".to_string())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
Err(err) => Err(format!("Failed to fetch entity properties: {:?}", err)),
|
||||||
Err(err) => log!("Error fetching entity label: {:?}", err),
|
|
||||||
}
|
|
||||||
|
|
||||||
entity_id.to_string() // Fallback to entity ID if label fetch fails
|
|
||||||
}
|
|
||||||
|
|
||||||
//function to fetch properties
|
|
||||||
async fn fetch_item_properties(wikidata_id: &str, set_fetched_properties: WriteSignal<HashMap<String, String>>, set_property_labels: WriteSignal<HashMap<String, String>>,) -> HashMap<String, String> {
|
|
||||||
let url = format!(
|
|
||||||
"https://www.wikidata.org/w/api.php?action=wbgetentities&ids={}&format=json&props=claims&origin=*",
|
|
||||||
wikidata_id
|
|
||||||
);
|
|
||||||
|
|
||||||
match gloo_net::http::Request::get(&url).send().await {
|
|
||||||
Ok(response) => {
|
|
||||||
if let Ok(data) = response.json::<serde_json::Value>().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 {
|
|
||||||
for value_entry in values.as_array().unwrap_or(&vec![]) {
|
|
||||||
if let Some(datavalue) = value_entry["mainsnak"]["datavalue"].get("value") {
|
|
||||||
let parsed_value = parse_property_value(datavalue).await;
|
|
||||||
result.insert(property.clone(), parsed_value);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch labels for the properties
|
// Function to fetch labels for properties
|
||||||
let property_ids = result.keys().cloned().collect::<Vec<_>>();
|
|
||||||
let labels = fetch_property_labels(property_ids).await;
|
|
||||||
set_property_labels.update(|labels_map| {
|
|
||||||
for (key, value) in labels {
|
|
||||||
labels_map.insert(key, value);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Update fetched properties
|
|
||||||
set_fetched_properties.update(|properties| {
|
|
||||||
for (key, val) in result.clone() {
|
|
||||||
properties.insert(key.clone(), val.clone());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(err) => log!("Error fetching item properties: {:?}", err),
|
|
||||||
}
|
|
||||||
|
|
||||||
HashMap::new()
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn fetch_property_labels(property_ids: Vec<String>) -> HashMap<String, String> {
|
async fn fetch_property_labels(property_ids: Vec<String>) -> HashMap<String, String> {
|
||||||
let mut property_labels = HashMap::new();
|
let mut property_labels = HashMap::new();
|
||||||
|
|
||||||
|
@ -436,13 +429,13 @@ pub fn ItemsList(
|
||||||
property_labels
|
property_labels
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a new custom property
|
// Function to add a new custom property
|
||||||
let add_property = move |property: String| {
|
let add_property = move |property: String| {
|
||||||
set_custom_properties.update(|props| {
|
set_custom_properties.update(|props| {
|
||||||
if !props.contains(&property) && !property.is_empty() {
|
if !props.contains(&property) && !property.is_empty() {
|
||||||
props.push(property.clone());
|
props.push(property.clone());
|
||||||
|
|
||||||
//update the selected_properties state when a new property is added
|
// Update the selected_properties state when a new property is added
|
||||||
set_selected_properties.update(|selected| {
|
set_selected_properties.update(|selected| {
|
||||||
selected.insert(property.clone(), true);
|
selected.insert(property.clone(), true);
|
||||||
});
|
});
|
||||||
|
@ -463,15 +456,18 @@ pub fn ItemsList(
|
||||||
// Fetch the property label
|
// Fetch the property label
|
||||||
let property_id = property.clone();
|
let property_id = property.clone();
|
||||||
spawn_local(async move {
|
spawn_local(async move {
|
||||||
let labels = fetch_property_labels(vec![property_id.clone()]).await;
|
let labels = fetch_entity_labels(vec![property_id.clone()]).await;
|
||||||
|
if let Ok(labels) = labels {
|
||||||
|
if let Some((_, label)) = labels.first() {
|
||||||
set_property_labels.update(|labels_map| {
|
set_property_labels.update(|labels_map| {
|
||||||
if let Some(label) = labels.get(&property_id) {
|
|
||||||
labels_map.insert(property_id, label.clone());
|
labels_map.insert(property_id, label.clone());
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Fetch the relevant value for each item and populate the corresponding cells
|
// Fetch the relevant value for each item and populate the corresponding cells
|
||||||
set_items.update(|items| {
|
set_items.update(|items| {
|
||||||
for item in items {
|
for item in items {
|
||||||
|
@ -481,22 +477,25 @@ pub fn ItemsList(
|
||||||
let set_property_labels = set_property_labels.clone();
|
let set_property_labels = set_property_labels.clone();
|
||||||
let property_clone = property.clone();
|
let property_clone = property.clone();
|
||||||
spawn_local(async move {
|
spawn_local(async move {
|
||||||
let properties = fetch_item_properties(&wikidata_id, set_fetched_properties, set_property_labels).await;
|
let properties = fetch_entity_properties(wikidata_id).await;
|
||||||
// log!("Fetched properties for Wikidata ID {}: {:?}", wikidata_id, properties);
|
if let Ok(properties) = properties {
|
||||||
if let Some(value) = properties.get(&property_clone) {
|
for (property, value) in properties {
|
||||||
|
if property == &property_clone {
|
||||||
set_items.update(|items| {
|
set_items.update(|items| {
|
||||||
if let Some(item) = items.iter_mut().find(|item| item.wikidata_id.as_ref().unwrap() == &wikidata_id) {
|
if let Some(item) = items.iter_mut().find(|item| item.wikidata_id.as_ref().unwrap() == &wikidata_id) {
|
||||||
item.custom_properties.insert(property_clone.clone(), value.clone());
|
item.custom_properties.insert(property_clone.clone(), value.clone());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// Update item fields
|
// Function to update item fields
|
||||||
let update_item = move |index: usize, field: &str, value: String| {
|
let update_item = move |index: usize, field: &str, value: String| {
|
||||||
set_items.update(|items| {
|
set_items.update(|items| {
|
||||||
if let Some(item) = items.get_mut(index) {
|
if let Some(item) = items.get_mut(index) {
|
||||||
|
@ -512,8 +511,10 @@ pub fn ItemsList(
|
||||||
let set_fetched_properties = set_fetched_properties.clone();
|
let set_fetched_properties = set_fetched_properties.clone();
|
||||||
let set_property_labels = set_property_labels.clone();
|
let set_property_labels = set_property_labels.clone();
|
||||||
spawn_local(async move {
|
spawn_local(async move {
|
||||||
let properties = fetch_item_properties(&wikidata_id, set_fetched_properties, set_property_labels).await;
|
let properties = fetch_entity_properties(wikidata_id).await;
|
||||||
|
if let Ok(properties) = properties {
|
||||||
log!("Fetched properties for index {}: {:?}", index, properties);
|
log!("Fetched properties for index {}: {:?}", index, properties);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -539,7 +540,6 @@ pub fn ItemsList(
|
||||||
id: Uuid::new_v4().to_string(),
|
id: Uuid::new_v4().to_string(),
|
||||||
name: String::new(),
|
name: String::new(),
|
||||||
description: String::new(),
|
description: String::new(),
|
||||||
// reviews: vec![],
|
|
||||||
wikidata_id: None,
|
wikidata_id: None,
|
||||||
custom_properties: HashMap::new(),
|
custom_properties: HashMap::new(),
|
||||||
};
|
};
|
||||||
|
@ -654,9 +654,8 @@ pub fn ItemsList(
|
||||||
let set_fetched_properties = set_fetched_properties.clone();
|
let set_fetched_properties = set_fetched_properties.clone();
|
||||||
let set_property_labels = set_property_labels.clone();
|
let set_property_labels = set_property_labels.clone();
|
||||||
spawn_local(async move {
|
spawn_local(async move {
|
||||||
let properties = fetch_item_properties(&wikidata_id, set_fetched_properties, set_property_labels).await;
|
let properties = fetch_entity_properties(wikidata_id).await;
|
||||||
// log!("Fetched properties for Wikidata ID {}: {:?}", wikidata_id, properties);
|
if let Ok(properties) = properties {
|
||||||
|
|
||||||
// Populate the custom properties for the new item
|
// Populate the custom properties for the new item
|
||||||
set_items.update(|items| {
|
set_items.update(|items| {
|
||||||
if let Some(item) = items.iter_mut().find(|item| item.wikidata_id.as_ref() == Some(&wikidata_id)) {
|
if let Some(item) = items.iter_mut().find(|item| item.wikidata_id.as_ref() == Some(&wikidata_id)) {
|
||||||
|
@ -665,6 +664,7 @@ pub fn ItemsList(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Hide the suggestion list
|
// Hide the suggestion list
|
||||||
|
|
Loading…
Add table
Reference in a new issue