fix(labels): display correct labels in dropdown and when properties are added

This commit is contained in:
ryan 2025-03-31 23:50:35 +03:00
parent 9d21d9999f
commit 8c7946091f

View file

@ -143,10 +143,6 @@ pub fn ItemsList(
// State to manage property cache
let (property_cache, set_property_cache) = create_signal(HashMap::<String, HashMap<String, String>>::new());
// State to track when labels are being fetched
let (is_fetching_labels, set_is_fetching_labels) = create_signal(false);
#[cfg(feature = "ssr")]
fn get_current_url() -> String {
use leptos::use_context;
@ -210,11 +206,7 @@ pub fn ItemsList(
// Fetch labels for the custom properties
let property_ids = custom_props_clone;
let labels = fetch_property_labels(
property_ids,
set_property_labels.clone(),
move |value| set_is_fetching_labels.set(value),
).await;
let labels = fetch_property_labels(property_ids).await;
set_property_labels.update(|labels_map| {
for (key, value) in labels {
labels_map.insert(key, value);
@ -397,7 +389,6 @@ pub fn ItemsList(
property_cache: ReadSignal<HashMap<String, HashMap<String, String>>>,
set_property_cache: WriteSignal<HashMap<String, HashMap<String, String>>>,
property_labels: ReadSignal<HashMap<String, String>>,
set_is_fetching_labels: WriteSignal<bool>,
) -> HashMap<String, String> {
// Check cache first
@ -454,12 +445,7 @@ pub fn ItemsList(
.collect();
if !missing_ids.is_empty() {
let new_labels = fetch_property_labels(
missing_ids,
set_property_labels.clone(),
move |value| { set_is_fetching_labels.set(value) },
).await;
let new_labels = fetch_property_labels(missing_ids).await;
set_property_labels.update(|labels| {
labels.extend(new_labels.clone());
});
@ -468,13 +454,27 @@ pub fn ItemsList(
// Second pass: build results
if let Some(bindings) = data["results"]["bindings"].as_array() {
for binding in bindings {
if let (Some(prop), Some(value_label)) = (
binding["propLabel"]["value"].as_str(),
binding["valueLabel"]["value"].as_str(),
if let (Some(prop_uri), Some(value_label)) = (
binding["prop"]["value"].as_str(),
binding["valueLabel"]["value"].as_str()
) {
let prop_id = prop.replace("http://www.wikidata.org/prop/", "");
// Extract property ID from URI (e.g., "http://www.wikidata.org/prop/P123")
let prop_id = prop_uri.split('/').last().unwrap_or_default().to_string();
// Get the label from property_labels signal
if let Some(label) = property_labels.get().get(&prop_id).cloned() {
result.insert(label.clone(), value_label.to_string());
result.insert(
prop_id.clone(),
format!("{}: {}",
property_labels.get().get(&prop_id).cloned().unwrap_or(prop_id.clone()),
value_label
)
);
// Ensure the label is stored in property_labels
set_property_labels.update(|labels| {
labels.entry(prop_id.clone()).or_insert_with(|| label.clone());
});
}
}
}
@ -494,12 +494,7 @@ pub fn ItemsList(
}
}
async fn fetch_property_labels(
property_ids: Vec<String>,
set_property_labels: WriteSignal<HashMap<String, String>>,
set_is_fetching_labels: impl Fn(bool) + 'static,
) -> HashMap<String, String> {
set_is_fetching_labels(true);
async fn fetch_property_labels(property_ids: Vec<String>) -> HashMap<String, String> {
log!("Fetching property labels for properties: {:?}", property_ids);
// Remove the "http://www.wikidata.org/prop/" prefix from property IDs
@ -551,8 +546,7 @@ pub fn ItemsList(
binding["prop"]["value"].as_str(),
binding["propLabel"]["value"].as_str()
) {
let prop_id =
prop.split('/').last().unwrap_or("").to_string();
let prop_id = prop.split('/').last().unwrap_or("").to_string();
result.insert(prop_id.clone(), label.to_string());
log!("Processed binding {}: prop_id = {}, label = {}", i, prop_id, label);
} else {
@ -563,7 +557,6 @@ pub fn ItemsList(
log!("Warning: No bindings found in the response");
}
log!("Fetched {} property labels", result.len());
set_is_fetching_labels(false);
result
}
Err(e) => {
@ -603,12 +596,7 @@ pub fn ItemsList(
let normalized_property = normalized_property.clone();
let set_property_labels = set_property_labels.clone();
async move {
let labels = fetch_property_labels(
vec![normalized_property.clone()],
set_property_labels.clone(),
move |value| set_is_fetching_labels.set(value),
)
.await;
let labels = fetch_property_labels(vec![normalized_property.clone()]).await;
set_property_labels.update(|map| {
map.extend(labels);
});
@ -686,34 +674,36 @@ pub fn ItemsList(
// Fetch the relevant value for each item and populate the corresponding cells
set_items.update(|items| {
for item in items {
// Initialize property with empty string if it doesn't exist
item.custom_properties.entry(normalized_property.clone())
.or_insert_with(|| "".to_string());
// Only fetch properties if Wikidata ID exists
if let Some(wikidata_id) = &item.wikidata_id {
let wikidata_id = wikidata_id.clone();
let set_items = set_items.clone();
let set_fetched_properties = set_fetched_properties.clone();
let set_property_labels = set_property_labels.clone();
let property_clone = property.clone();
let property_clone = normalized_property.clone();
spawn_local(async move {
let properties = fetch_item_properties(
&wikidata_id,
set_property_labels.clone(),
property_cache.clone(),
set_property_cache.clone(),
property_labels.clone(),
set_is_fetching_labels.clone()
)
.await;
// Update fetched properties and property labels
set_fetched_properties.update(|fp| {
fp.insert(wikidata_id.clone(), properties.clone());
});
set_property_labels.update(|pl| {
for (key, value) in properties.iter() {
pl.entry(key.clone()).or_insert_with(|| value.clone());
}
});
property_labels.clone()
).await;
// Update the specific property for this item
if let Some(value) = properties.get(&property_clone) {
set_items.update(|items| {
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());
if let Some(item) = items.iter_mut()
.find(|i| i.wikidata_id.as_ref() == Some(&wikidata_id))
{
item.custom_properties.insert(
property_clone.clone(),
value.clone()
);
}
});
}
@ -721,8 +711,7 @@ pub fn ItemsList(
}
}
});
})
};
})};
// Update item fields
let update_item = {
@ -743,15 +732,7 @@ pub fn ItemsList(
if let Some(wikidata_id) = &item.wikidata_id {
let wikidata_id = wikidata_id.clone();
spawn_local(async move {
let properties = fetch_item_properties(
&wikidata_id,
set_property_labels.clone(),
property_cache.clone(),
set_property_cache.clone(),
property_labels.clone(),
set_is_fetching_labels.clone()
)
.await;
let properties = fetch_item_properties(&wikidata_id, set_property_labels.clone(), property_cache.clone(), set_property_cache.clone(), property_labels.clone()).await;
log!("Fetched properties for index {}: {:?}", index, properties);
});
}
@ -797,8 +778,7 @@ pub fn ItemsList(
}
log!("Items updated: {:?}", items);
});
})
};
})};
// List of properties to display as rows
let properties = vec!["Name", "Description"];
@ -901,7 +881,7 @@ pub fn ItemsList(
// Fetch additional properties from Wikidata
let wikidata_id = id.clone();
spawn_local(async move {
let properties = fetch_item_properties(&wikidata_id, set_property_labels.clone(), property_cache.clone(), set_property_cache.clone(), property_labels.clone(),set_is_fetching_labels.clone()).await;
let properties = fetch_item_properties(&wikidata_id, set_property_labels.clone(), property_cache.clone(), set_property_cache.clone(), property_labels.clone()).await;
// log!("Fetched properties for Wikidata ID {}: {:?}", wikidata_id, properties);
// Populate the custom properties for the new item
@ -977,20 +957,10 @@ pub fn ItemsList(
let property_label = property_labels.get().get(&normalized_property).cloned().unwrap_or_else(|| normalized_property.clone());
log!("Rendering property: {} -> {}", normalized_property, property_label);
let property_clone_for_button = normalized_property.clone();
let normalized_property_clone = normalized_property.clone();
view! {
<tr>
<td>
{move || {
let property_label = property_labels.get().get(&normalized_property).cloned();
let is_fetching = is_fetching_labels.get();
if is_fetching {
normalized_property.clone()
} else {
property_label.unwrap_or_else(|| normalized_property.clone())
}
}}
{ property_label }
<button class="delete-property" on:click=move |_| {
log!("Deleting property: {}", property_clone_for_button);
remove_property_clone(property_clone_for_button.clone());
@ -1007,11 +977,9 @@ pub fn ItemsList(
});
}>{ "Delete" }</button>
</td>
let normalized_property = property.replace("http://www.wikidata.org/prop/", "");
let normalized_property_clone = normalized_property.clone();
{move || {
let update_item_cell = Arc::clone(&update_item_inner);
let property_clone_for_cells = normalized_property_clone.clone();
let property_clone_for_cells = normalized_property.clone();
items.get().iter().enumerate().map(move |(index, item)| {
let update_item_cell = Arc::clone(&update_item_cell);
let property_clone_for_closure = property_clone_for_cells.clone();
@ -1043,15 +1011,19 @@ pub fn ItemsList(
<input type="text" id="new-property" placeholder="Add New Property" list="properties" on:keydown=move |event| {
if event.key() == "Enter" {
let input_element = event.target().unwrap().dyn_into::<web_sys::HtmlInputElement>().unwrap();
let property = input_element.value();
if !property.is_empty() {
// Extract the coded name from the selected value
let coded_name = property.split(" - ").next().unwrap_or(&property).to_string();
let input_value = input_element.value();
// Add the property using the coded name
add_property(coded_name);
// Extract property ID from "Label (P123)" format
let property_id = input_value
.split(" (")
.last()
.and_then(|s| s.strip_suffix(')'))
.unwrap_or(&input_value)
.to_string();
// Clear the input field
if !property_id.is_empty() {
// Add the property using the extracted ID
add_property(property_id);
input_element.set_value("");
}
}
@ -1059,10 +1031,11 @@ pub fn ItemsList(
<datalist id="properties">
{move || {
let property_labels = property_labels.get().clone();
property_labels.into_iter().map(|(property, label)| {
let property_clone = property.clone();
property_labels.into_iter().map(|(property_id, label)| {
view! {
<option value={property}>{ format!("{}", property_clone) }</option>
<option value={format!("{} ({})", label, property_id)}>
{ format!("{} ({})", label, property_id) }
</option>
}
}).collect::<Vec<_>>()
}}