Compare commits

..

1 commit
main ... dev

2 changed files with 92 additions and 81 deletions

View file

@ -22,17 +22,19 @@ pub fn EditableCell(
let new_value = match input_type_clone { let new_value = match input_type_clone {
InputType::Text => event_target_value(&e), InputType::Text => event_target_value(&e),
InputType::TextArea => event_target_value(&e), InputType::TextArea => event_target_value(&e),
InputType::Search => event_target_value(&e),
}; };
log!("Input event: {}", new_value); log!("Input event: {}", new_value);
set_local_value.set(new_value); set_local_value.set(new_value.clone());
on_input(new_value);
}; };
// Commit the input value on blur or enter // // Commit the input value on blur or enter
let commit_input = move || { // let commit_input = move || {
let value = local_value.get(); // let value = local_value.get();
log!("Committing input: {}", value); // log!("Committing input: {}", value);
on_input(value); // on_input(value);
}; // };
// Focus handling // Focus handling
let handle_focus = { let handle_focus = {
@ -49,7 +51,7 @@ pub fn EditableCell(
let handle_blur = move |_| { let handle_blur = move |_| {
log!("Focus lost"); log!("Focus lost");
set_focused_cell.set(None); set_focused_cell.set(None);
commit_input(); // commit_input();
if let Some(on_blur) = &on_blur { if let Some(on_blur) = &on_blur {
on_blur.call(()); on_blur.call(());
} }
@ -58,10 +60,23 @@ pub fn EditableCell(
// Update input field value when focused cell changes // Update input field value when focused cell changes
create_effect(move |_| { create_effect(move |_| {
if focused_cell.get().as_deref() == Some(key.as_str()) { if focused_cell.get().as_deref() == Some(key.as_str()) {
log!("Setting focus for key: {}", key); log!("Persisting focus for key: {}", key);
if let Some(input) = input_ref.get() { let input_ref = input_ref.clone();
let _ = input.focus(); let key_clone = key.clone();
}
// Use requestAnimationFrame for better focus timing
spawn_local(async move {
for _ in 0..3 { // Retry up to 3 times
gloo_timers::future::sleep(std::time::Duration::from_millis(10)).await;
if let Some(input) = input_ref.get() {
let _ = input.focus();
if document().active_element().as_ref() == Some(input.as_ref() as &web_sys::Element) {
break;
}
}
log!("Focus retry for {}", key_clone);
}
});
} }
}); });
@ -88,6 +103,17 @@ pub fn EditableCell(
node_ref=textarea_ref node_ref=textarea_ref
class="editable-cell-input" class="editable-cell-input"
/> />
}.into_view(),
InputType::Search => view! {
<input
type="search"
prop:value=move || local_value.get()
on:input=handle_input
on:focus=handle_focus
on:blur=handle_blur
node_ref=input_ref
class="editable-cell-input"
/>
}.into_view() }.into_view()
}} }}
</div> </div>
@ -98,4 +124,5 @@ pub fn EditableCell(
pub enum InputType { pub enum InputType {
Text, Text,
TextArea, TextArea,
Search
} }

View file

@ -814,108 +814,92 @@ pub fn ItemsList(
<td> <td>
{match property { {match property {
"Name" => view! { "Name" => view! {
<div class="editable-cell"> <div class="search-container">
<EditableCell <EditableCell
value=item.name.clone() value=item.name.clone()
on_input=move |value| { on_input=move |value| {
update_item_clone(index, "name", value.clone()); update_item_clone(index, "name", value.clone());
fetch_wikidata_suggestions(format!("name-{}", index), value); // Debounce with proper async handling
spawn_local({
let key = format!("name-{}", index);
let value = value.clone();
let fetch = fetch_wikidata_suggestions.clone();
async move {
gloo_timers::future::sleep(std::time::Duration::from_millis(300)).await;
fetch(key, value);
}
});
} }
key=Arc::new(format!("name-{}", index)) key=Arc::new(format!("name-{}", index))
focused_cell=focused_cell focused_cell=focused_cell
set_focused_cell=set_focused_cell.clone() set_focused_cell=set_focused_cell.clone()
on_focus=Some(Callback::new(move |_| { on_focus=Some(Callback::new(move |_| {
log!("Input focused, showing suggestions");
set_show_suggestions.update(|suggestions| { set_show_suggestions.update(|suggestions| {
suggestions.insert(format!("name-{}", index), true); suggestions.insert(format!("name-{}", index), true);
}); });
})) }))
on_blur=Some(Callback::new(move |_| { on_blur=Some(Callback::new(move |_| {
log!("Input blurred, delaying hiding suggestions");
spawn_local(async move { spawn_local(async move {
gloo_timers::future::sleep(std::time::Duration::from_millis(500)).await;
log!("Hiding suggestions after delay");
set_show_suggestions.update(|suggestions| { set_show_suggestions.update(|suggestions| {
suggestions.insert(format!("name-{}", index), false); suggestions.insert(format!("name-{}", index), false);
}); });
}); });
})) }))
input_type=InputType::Text input_type=InputType::Search
/> />
<button class="search-icon" on:click=move |_| {
log!("Search icon clicked, showing suggestions");
set_show_suggestions.update(|suggestions| {
suggestions.insert(format!("name-{}", index), true);
});
}>
<i class="fas fa-search"></i> Search Wiki
</button>
{move || { {move || {
if *show_suggestions.get().get(&format!("name-{}", index)).unwrap_or(&false) { if *show_suggestions.get().get(&format!("name-{}", index)).unwrap_or(&false) {
log!("Rendering suggestions list");
view! { view! {
<ul class="editable-cell-suggestions"> <div class="suggestions-container">
{move || { <ul class="suggestions-list">
let suggestions = wikidata_suggestions.get() {move || {
.get(&format!("name-{}", index)) let suggestions = wikidata_suggestions.get()
.cloned() .get(&format!("name-{}", index))
.unwrap_or_default(); .cloned()
log!("Suggestions for cell {}: {:?}", index, suggestions); .unwrap_or_default();
suggestions.into_iter().map(|suggestion| { suggestions.into_iter().map(|suggestion| {
let label_for_click = suggestion.label.clone(); let label = suggestion.label.clone();
let label_for_display = suggestion.label.clone(); let description = suggestion.description.clone().unwrap_or_default();
let description_for_click = suggestion.description.clone().unwrap_or_default(); let id = suggestion.id.clone();
let description_for_display = suggestion.description.clone().unwrap_or_default();
let id = suggestion.id.clone();
view! {
<li class="editable-cell-suggestions-li" on:click=move |_| {
// Update item with basic suggestion details
set_items.update(|items| {
if let Some(item) = items.get_mut(index) {
item.description = description_for_click.clone();
item.wikidata_id = Some(id.clone());
item.name = label_for_click.clone();
}
});
// Fetch additional properties from Wikidata // Clone values for the closure
let wikidata_id = id.clone(); let closure_label = label.clone();
spawn_local(async move { let closure_description = description.clone();
let properties = fetch_item_properties(&wikidata_id, set_property_labels.clone(), property_cache.clone(), set_property_cache.clone(), property_labels.clone()).await; let closure_id = id.clone();
// log!("Fetched properties for Wikidata ID {}: {:?}", wikidata_id, properties);
view! {
// Populate the custom properties for the new item <li
set_items.update(|items| { class="suggestion-item"
if let Some(item) = items.iter_mut().find(|item| item.wikidata_id.as_ref() == Some(&wikidata_id)) { on:click=move |_| {
for (property, value) in properties { set_items.update(|items| {
item.custom_properties.insert(property, value); if let Some(item) = items.get_mut(index) {
item.name = closure_label.clone();
item.description = closure_description.clone();
item.wikidata_id = Some(closure_id.clone());
} }
} });
}); set_show_suggestions.update(|s| {
}); s.insert(format!("name-{}", index), false);
});
// Hide the suggestion list }
set_show_suggestions.update(|suggestions| { >
suggestions.insert(format!("name-{}", index), false); <div class="suggestion-title">{label}</div>
log!("Updated show_suggestions: {:?}", suggestions); <div class="suggestion-description">{description}</div>
}); // <div class="suggestion-id">{id}</div>
}> </li>
{ format!("{} - {}", label_for_display, description_for_display) } }
</li> }).collect::<Vec<_>>()
} }}
}).collect::<Vec<_>>()
}}
</ul> </ul>
</div>
} }
} else { } else {
log!("Suggestions list hidden"); view! { <div></div> }
view! {
<ul></ul>
}
} }
}} }}
</div> </div>
}.into_view(), }.into_view(),
"Description" => view! { "Description" => view! {
<EditableCell <EditableCell
value=item.description.clone() value=item.description.clone()